diff --git a/.bandit.yml b/.bandit.yml new file mode 100644 index 0000000..a0e3247 --- /dev/null +++ b/.bandit.yml @@ -0,0 +1,3 @@ +skips: +- B603 # Ignore warnings about calling subprocess.Popen without shell=True +- B607 # Ignore warnings about calling subprocess.Popen without a full path to executable diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..029a5d6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +*.pyc +__pycache__ +.tox +.coverage + +# vim swapfiles +*.sw? + +# virtual environment +.venv/ + +# python packaging +MANIFEST +dist/ +build/ +*.egg-info/ + +# Pycharm stuff +.idea/ diff --git a/CHANGES.txt b/CHANGES.txt index 83ad7b8..9cc2496 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,238 @@ +Revision 0.4.1, released 10-09-2024 +--------------------------------------- + +- Added support for Python 3.13 + +Revision 0.4.0, released 26-03-2024 +--------------------------------------- + +- Added support for Python 3.11, 3.12 +- Removed support for EOL Pythons 2.7, 3.6, 3.7 + +Revision 0.3.0, released 19-04-2023 +--------------------------------------- + +- Added support for Python 3.8, 3.9, 3.10, 3.11 +- Removed support for EOL Pythons 2.4, 2.5, 2.6, 3.2, 3.3, 3.4, 3.5 +- Added support for PyPy 3.7, 3.8, 3.9 +- Modernized packaging and testing. pyasn1-modules now uses ``setup.cfg``, + ``pyproject.toml``, [build](https://pypi.org/project/build/), and + GitHub Actions. +- PyPI package ownership for `pyasn1` and `pyasn1-module` has been + transfered to *Christian Heimes* and *Simon Pichugin* in + [PyPI support ticket #2090](https://github.com/pypa/pypi-support/issues/2090). +- The upstream repositories for `pyasn1` and `pyasn1-modules` are now + in the GitHub organization https://github.com/pyasn1/. +- Added tox runner with a handful of basic jobs +- Add RFC3125 providing Electronic Signature Policies +- Add RFC5126 providing CMS Advanced Electronic Signatures (CAdES) +- Removed support for EOL Pythons 2.4, 2.5, 2.6, 3.2, 3.3 and 3.4. +- Improve test routines for RFC5126 +- Add RFC4387 providing Certificate Store Access via HTTP +- Changed assertion in unit tests from Python built-in to `unittest` + provided +- Add RFC8692 providing Algorithm Identifiers for RSASSA-PSS and + ECDSA Using SHAKEs +- Add RFC5753 providing CMS Elliptic Curve Cryptography Algorithms +- Add RFC3820 providing Proxy Certificates +- Add RFC3370 providing Cryptographic Message Syntax (CMS) Algorithms +- Add RFC3537 providing HMAC Key Wrapping +- Add RFC3739 providing Qualified Certificates +- Add RFC2876 providing KEA and SKIPJACK for CMS +- Add RFC3058 providing IDEA Encryption Algorithm for CMS +- Add RFC3657 providing Camellia Encryption Algorithm for CMS +- Add RFC4010 providing SEED Encryption Algorithm for CMS +- Add RFC4357 providing Additional Cryptographic Algorithms for Use with + GOST 28147-89, GOST R 34.10-94, GOST R 34.10-2001, and GOST R 34.11-94 +- Add RFC4490 providing GOST 28147-89, GOST R 34.11-94, GOST R 34.10-94, + and GOST R 34.10-2001 Algorithms for CMS +- Add RFC4491 providing GOST R 34.10-94, GOST R 34.10-2001, and + GOST R 34.11-94 Algorithms for certificates and CRLs +- Add RFC8696 providing using Pre-Shared Key (PSK) in the CMS +- Add RFC5639 providing identifiers for the Brainpool curves in + Elliptic Curve Cryptography +- Add RFC5697 providing Other Certificates Extension +- Add RFC4683 providing Subject Identification Method (SIM) +- Add RFC4476 providing Attribute Certificate Policies Extension +- Add RFC5636 providing Traceable Anonymous Certificate +- Add RFC5752 providing Multiple Signatures attribute for CMS +- Add RFC5275 providing CMS Symmetric Key Management and Distribution +- Add RFC8702 providing SHAKE One-way Hash Functions in the CMS +- Add RFC8708 providing HSS/LMS Hash-based Signature Algorithm for CMS +- Advance copyright statement to year 2020 +- Add RFC8769 providing CBOR and CBOR Sequence content types for CMS + +Revision 0.2.8, released 16-11-2019 +----------------------------------- + +- Improve test routines for modules that use certificate extensions +- Improve test for RFC3709 with a real world certificate +- Added RFC7633 providing TLS Features Certificate Extension +- Added RFC7229 providing OIDs for Test Certificate Policies +- Added tests for RFC3280, RFC3281, RFC3852, and RFC4211 +- 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 +- Added RFC6487 providing Profile for X.509 PKIX Resource Certificates +- Added RFC6170 providing Certificate Image in the Internet X.509 Public + Key Infrastructure, and import the object identifier into RFC3709. +- Added RFC6187 providing Certificates for Secure Shell Authentication +- Added RFC6482 providing RPKI Route Origin Authorizations (ROAs) +- Added RFC6664 providing S/MIME Capabilities for Public Keys +- Added RFC6120 providing Extensible Messaging and Presence Protocol + names in certificates +- Added RFC4985 providing Subject Alternative Name for expression of + service names in certificates +- Added RFC5924 providing Extended Key Usage for Session Initiation + Protocol (SIP) in X.509 certificates +- Added RFC5916 providing Device Owner Attribute +- Added RFC7508 providing Securing Header Fields with S/MIME +- Update RFC8226 to use ComponentPresentConstraint() instead of the + previous work around +- Add RFC2631 providing OtherInfo for Diffie-Hellman Key Agreement +- Add RFC3114 providing test values for the S/MIME Security Label +- Add RFC5755 providing Attribute Certificate Profile for Authorization +- Add RFC5913 providing Clearance Attribute and Authority Clearance + Constraints Certificate Extension +- Add RFC5917 providing Clearance Sponsor Attribute +- 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 +----------------------------------- + +- Added maps for use with openType to RFC 3565 +- Added RFC2985 providing PKCS#9 Attributes +- Added RFC3770 providing Certificate Extensions and Attributes for + Authentication in PPP and Wireless LAN Networks +- Added RFC5914 providing Trust Anchor Format +- Added RFC6010 providing CMS Content Constraints (CCC) Extension +- Added RFC6031 providing CMS Symmetric Key Package Content Type +- Added RFC6032 providing CMS Encrypted Key Package Content Type +- Added RFC7030 providing Enrollment over Secure Transport (EST) +- Added RFC7292 providing PKCS #12, which is the Personal Information + Exchange Syntax v1.1 +- Added RFC8018 providing PKCS #5, which is the Password-Based + Cryptography Specification, Version 2.1 +- Automatically update the maps for use with openType for RFC3709, + RFC6402, RFC7191, and RFC8226 when the module is imported +- Added RFC6211 providing CMS Algorithm Identifier Protection Attribute +- Added RFC8449 providing Certificate Extension for Hash Of Root Key +- Updated RFC2459 and RFC5280 for TODO in the certificate extension map +- Added RFC7906 providing NSA's CMS Key Management Attributes +- Added RFC7894 providing EST Alternative Challenge Password Attributes +- Updated the handling of maps for use with openType so that just doing + an import of the modules is enough in most situations; updates to + RFC 2634, RFC 3274, RFC 3779, RFC 4073, RFC 4108, RFC 5035, RFC 5083, + RFC 5084, RFC 5480, RFC 5940, RFC 5958, RFC 6019, and RFC 8520 +- Updated the handling of attribute maps for use with openType in + RFC 5958 to use the rfc5652.cmsAttributesMap +- Added RFC5990 providing RSA-KEM Key Transport Algorithm in the CMS +- Fixed malformed `rfc4210.RevRepContent` data structure layout +- Added RFC5934 providing Trust Anchor Management Protocol (TAMP) +- Added RFC6210 providing Experiment for Hash Functions with Parameters +- Added RFC5751 providing S/MIME Version 3.2 Message Specification +- Added RFC8494 providing Multicast Email (MULE) over ACP 142 +- Added RFC8398 providing Internationalized Email Addresses in + X.509 Certificates +- Added RFC8419 providing Edwards-Curve Digital Signature Algorithm + (EdDSA) Signatures in the CMS +- Added RFC8479 providing Storing Validation Parameters in PKCS#8 +- Added RFC8360 providing Resource Public Key Infrastructure (RPKI) + Validation Reconsidered +- Added RFC8358 providing Digital Signatures on Internet-Draft Documents +- Added RFC8209 providing BGPsec Router PKI Profile +- Added RFC8017 providing PKCS #1 Version 2.2 +- Added RFC7914 providing scrypt Password-Based Key Derivation Function +- Added RFC7773 providing Authentication Context Certificate Extension + +Revision 0.2.6, released 31-07-2019 +----------------------------------- + +- Added RFC3560 providing RSAES-OAEP Key Transport Algorithm + in CMS +- Added RFC6019 providing BinaryTime - an alternate format + for representing Date and Time +- RFC3565 superseded by RFC5649 +- Added RFC5480 providng Elliptic Curve Cryptography Subject + Public Key Information +- Added RFC8520 providing X.509 Extensions for MUD URL and + MUD Signer +- Added RFC3161 providing Time-Stamp Protocol support +- Added RFC3709 providing Logotypes in X.509 Certificates +- Added RFC3274 providing CMS Compressed Data Content Type +- Added RFC4073 providing Multiple Contents protection with CMS +- Added RFC2634 providing Enhanced Security Services for S/MIME +- Added RFC5915 providing Elliptic Curve Private Key +- Added RFC5940 providing CMS Revocation Information Choices +- Added RFC7296 providing IKEv2 Certificate Bundle +- Added RFC8619 providing HKDF Algorithm Identifiers +- Added RFC7191 providing CMS Key Package Receipt and Error Content + Types +- Added openType support for ORAddress Extension Attributes and + Algorithm Identifiers in the RFC5280 module +- Added RFC5035 providing Update to Enhanced Security Services for + S/MIME +- Added openType support for CMS Content Types and CMS Attributes + in the RFC5652 module +- Added openType support to RFC 2986 by importing definitions from + the RFC 5280 module so that the same maps are used. +- Added maps for use with openType to RFC 2634, RFC 3274, RFC 3709, + RFC 3779, RFC 4055, RFC 4073, RFC 4108, RFC 5035, RFC 5083, RFC 5480, + RFC 5940, RFC 5958, RFC 6010, RFC 6019, RFC 6402, RFC 7191, RFC 8226, + and RFC 8520 +- Changed `ValueSizeConstraint` erroneously applied to `SequenceOf` + and `SetOf` objects via `subtypeConstraint` attribute to be applied + via `sizeSpec` attribute. Although `sizeSpec` takes the same constraint + objects as `subtypeConstraint`, the former is only verified on + de/serialization i.e. when the [constructed] object at hand is fully + populated, while the latter is applied to [scalar] types at the moment + of instantiation. + +Revision 0.2.5, released 24-04-2019 +----------------------------------- + +- Added module RFC5958 providing Asymmetric Key Packages, + which is essentially version 2 of the PrivateKeyInfo + structure in PKCS#8 in RFC 5208 +- Added module RFC8410 providing algorithm Identifiers for + Ed25519, Ed448, X25519, and X448 +- Added module RFC8418 providing Elliptic Curve Diffie-Hellman + (ECDH) Key Agreement Algorithm with X25519 and X448 +- Added module RFC3565 providing Elliptic Curve Diffie-Hellman + Key Agreement Algorithm use with X25519 and X448 in the + Cryptographic Message Syntax (CMS) +- Added module RFC4108 providing CMS Firmware Wrapper +- Added module RFC3779 providing X.509 Extensions for IP + Addresses and AS Identifiers +- Added module RFC4055 providing additional Algorithms and + Identifiers for RSA Cryptography for use in Certificates + and CRLs + +Revision 0.2.4, released 26-01-2018 +----------------------------------- + +- Added modules for RFC8226 implementing JWT Claim Constraints + and TN Authorization List for X.509 certificate extensions +- Fixed bug in `rfc5280.AlgorithmIdentifier` ANY type definition + +Revision 0.2.3, released 30-12-2018 +----------------------------------- + +- Added modules for RFC5083 and RFC5084 (CMS) +- Copyright notice extended to the year 2019 + +Revision 0.2.2, released 28-06-2018 +----------------------------------- + +- Copyright notice extended to the year 2018 +- Migrated references from SourceForge +- rfc2986 module added Revision 0.2.1, released 23-11-2017 ----------------------------------- diff --git a/LICENSE.txt b/LICENSE.txt index 02b45c4..598b843 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2005-2017, Ilya Etingof +Copyright (c) 2005-2020, Ilya Etingof All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/PKG-INFO b/PKG-INFO deleted file mode 100644 index efb1859..0000000 --- a/PKG-INFO +++ /dev/null @@ -1,35 +0,0 @@ -Metadata-Version: 1.1 -Name: pyasn1-modules -Version: 0.2.1 -Summary: A collection of ASN.1-based protocols modules. -Home-page: https://github.com/etingof/pyasn1-modules -Author: Ilya Etingof -Author-email: etingof@gmail.com -License: BSD -Description: A collection of ASN.1 modules expressed in form of pyasn1 classes. Includes protocols PDUs definition (SNMP, LDAP etc.) and various data structures (X.509, PKCS etc.). -Platform: any -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Console -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: Education -Classifier: Intended Audience :: Information Technology -Classifier: Intended Audience :: System Administrators -Classifier: Intended Audience :: Telecommunications Industry -Classifier: License :: OSI Approved :: BSD License -Classifier: Natural Language :: English -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.4 -Classifier: Programming Language :: Python :: 2.5 -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.2 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Topic :: Communications -Classifier: Topic :: System :: Monitoring -Classifier: Topic :: System :: Networking :: Monitoring -Classifier: Topic :: Software Development :: Libraries :: Python Modules diff --git a/README.md b/README.md index 7fd77d6..c70b1e8 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,32 @@ ASN.1 modules for Python ------------------------ -[![PyPI](https://img.shields.io/pypi/v/pyasn1-modules.svg?maxAge=2592000)](https://pypi.python.org/pypi/pyasn1-modules) -[![Python Versions](https://img.shields.io/pypi/pyversions/pyasn1-modules.svg)](https://pypi.python.org/pypi/pyasn1-modules/) -[![Build status](https://travis-ci.org/etingof/pyasn1-modules.svg?branch=master)](https://secure.travis-ci.org/etingof/pyasn1-modules) -[![Coverage Status](https://img.shields.io/codecov/c/github/etingof/pyasn1-modules.svg)](https://codecov.io/github/etingof/pyasn1-modules/) -[![GitHub license](https://img.shields.io/badge/license-BSD-blue.svg)](https://raw.githubusercontent.com/etingof/pyasn1-modules/master/LICENSE.txt) +[![PyPI](https://img.shields.io/pypi/v/pyasn1-modules.svg?maxAge=2592000)](https://pypi.org/project/pyasn1-modules) +[![Python Versions](https://img.shields.io/pypi/pyversions/pyasn1-modules.svg)](https://pypi.org/project/pyasn1-modules/) +[![Build status](https://github.com/pyasn1/pyasn1-modules/actions/workflows/main.yml/badge.svg)](https://github.com/pyasn1/pyasn1-modules/actions/workflows/main.yml) +[![Coverage Status](https://img.shields.io/codecov/c/github/pyasn1/pyasn1-modules.svg)](https://codecov.io/github/pyasn1/pyasn1-modules) +[![GitHub license](https://img.shields.io/badge/license-BSD-blue.svg)](https://raw.githubusercontent.com/pyasn1/pyasn1-modules/master/LICENSE.txt) -This is a small but growing collection of +The `pyasn1-modules` package contains a collection of [ASN.1](https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-X.208-198811-W!!PDF-E&type=items) -data structures expressed in Python terms using [pyasn1](https://github.com/etingof/pyasn1) data model. +data structures expressed as Python classes based on [pyasn1](https://github.com/pyasn1/pyasn1) +data model. If ASN.1 module you need is not present in this collection, try using [Asn1ate](https://github.com/kimgr/asn1ate) tool that compiles ASN.1 documents -into pyasn1 code. +into pyasn1 code. + +**NOTE:** The package is now maintained by *Christian Heimes* and +*Simon Pichugin* in project https://github.com/pyasn1/pyasn1-modules. Feedback -------- -If something does not work as expected, try browsing pyasn1 -[mailing list archives](https://sourceforge.net/p/pyasn1/mailman/pyasn1-users/) -or post your question -[to Stack Overflow](http://stackoverflow.com/questions/ask). -If you want to contribute ASN.1 modules you have converted into pyasn1, -please send me a pull request. +If something does not work as expected, +[open an issue](https://github.com/pyasn1/pyasn1-modules/issues) at GitHub +or post your question [on Stack Overflow](https://stackoverflow.com/questions/ask) + +New modules contributions are welcome via GitHub pull requests. -Copyright (c) 2005-2017, [Ilya Etingof](mailto:etingof@gmail.com). +Copyright (c) 2005-2020, [Ilya Etingof](mailto:etingof@gmail.com). All rights reserved. - diff --git a/debian/changelog b/debian/changelog index f022502..dc76d6b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,68 @@ +python-pyasn1-modules (0.4.1-2) unstable; urgency=medium + + * Team upload. + * Patch-out usage of deprecated pyasn1.compat.octets Python 2+3 shim + Closes: #1098604 + + -- Alexandre Detiste Sat, 22 Feb 2025 13:48:21 +0100 + +python-pyasn1-modules (0.4.1-1) unstable; urgency=medium + + * Team Upload + * New upstream version 0.4.1 + * Add build-dependency on python3-setuptools (Closes: #1080764) + * Use dh-sequence-python3 + + -- Alexandre Detiste Wed, 09 Oct 2024 22:19:14 +0200 + +python-pyasn1-modules (0.4.0-1) unstable; urgency=medium + + * New upstream version (Closes: #1051857). + + -- Emmanuel Arias Fri, 23 Aug 2024 11:04:37 -0300 + +python-pyasn1-modules (0.3.0-1) unstable; urgency=medium + + [ Debian Janitor ] + * Remove constraints unnecessary since buster: + + Build-Depends: Drop versioned constraint on python3-pyasn1. + + [ Thomas Goirand ] + * Switch d/watch to version 4 and mode=git, plus use github instead of + pypi.debian.net. + * New upstream release. + * Ran wrap-and-sort -bastk. + * Add pybuild-plugin-pyproject as build-depends. + * Switch the homepage to the Github project URL. + * Add autopkgtest. + + -- Thomas Goirand Mon, 08 Apr 2024 09:12:55 +0200 + +python-pyasn1-modules (0.2.8-1) unstable; urgency=low + + [ Debian Janitor ] + * Use versioned copyright format URI. + * Use secure URI in debian/watch. + * Use secure URI in Homepage field. + * Bump debhelper from deprecated 8 to 12. + * Set debhelper-compat version in Build-Depends. + * Set upstream metadata fields: Bug-Database, Bug-Submit, Repository, + Repository-Browse. + + [ Ondřej Nový ] + * d/control: Update Maintainer field with new Debian Python Team + contact address. + * d/control: Update Vcs-* fields with new Debian Python Team Salsa + layout. + + [ Debian Janitor ] + * Bump debhelper from old 12 to 13. + + [ Julien Cristau ] + * New upstream release. + + -- Julien Cristau Wed, 06 Apr 2022 11:09:34 +0200 + python-pyasn1-modules (0.2.1-1) unstable; urgency=medium * Take over under DPMT umbrella, Marc is still part of Uploaders diff --git a/debian/compat b/debian/compat deleted file mode 100644 index 45a4fb7..0000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -8 diff --git a/debian/control b/debian/control index b4f3e79..612ab72 100644 --- a/debian/control +++ b/debian/control @@ -1,18 +1,28 @@ Source: python-pyasn1-modules Section: python Priority: optional -Maintainer: Debian Python Modules Team -Uploaders: Marc Haber , -Build-Depends: debhelper (>= 8~), dh-python, - python3-all, python3-pyasn1 (>= 0.4.1) +Maintainer: Debian Python Team +Uploaders: + Marc Haber , +Build-Depends: + debhelper-compat (= 13), + pybuild-plugin-pyproject, + dh-sequence-python3, + python3-all, + python3-pyasn1, + python3-setuptools, +Rules-Requires-Root: no Standards-Version: 3.9.6 -Homepage: http://pypi.python.org/pypi/pyasn1-modules -Vcs-Git: https://salsa.debian.org/python-team/modules/python-pyasn1-modules.git -Vcs-Browser: https://salsa.debian.org/python-team/modules/python-pyasn1-modules +Homepage: https://github.com/pyasn1/pyasn1-modules +Vcs-Git: https://salsa.debian.org/python-team/packages/python-pyasn1-modules.git +Vcs-Browser: https://salsa.debian.org/python-team/packages/python-pyasn1-modules Package: python3-pyasn1-modules Architecture: all -Depends: ${misc:Depends}, ${python3:Depends}, python3-pyasn1 +Depends: + python3-pyasn1 (>= 0.4.6~), + ${misc:Depends}, + ${python3:Depends}, Description: Collection of protocols modules written in ASN.1 language (Python 3) This is a small but growing collection of ASN.1 data structures expressed in Python terms using pyasn1 data model. diff --git a/debian/copyright b/debian/copyright index 9763b68..5c921cc 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,4 +1,4 @@ -Format: http://dep.debian.net/deps/dep5 +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: pyasn1-modules Source: http://pypi.python.org/pypi/pyasn1-modules @@ -16,8 +16,8 @@ License: BSD-2-Clause and/or other materials provided with the distribution. . THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF @@ -25,7 +25,7 @@ License: BSD-2-Clause INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. + POSSIBILITY OF SUCH DAMAGE. Files: debian/* Copyright: 2012 Marc Haber diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..57d12cb --- /dev/null +++ b/debian/patches/series @@ -0,0 +1 @@ +str2octs.patch diff --git a/debian/patches/str2octs.patch b/debian/patches/str2octs.patch new file mode 100644 index 0000000..505000e --- /dev/null +++ b/debian/patches/str2octs.patch @@ -0,0 +1,137 @@ +From: Alexandre Detiste +Forwarded: https://github.com/pyasn1/pyasn1-modules/pull/24 + +--- a/tests/test_rfc3770.py ++++ b/tests/test_rfc3770.py +@@ -10,7 +10,6 @@ + + from pyasn1.codec.der.decoder import decode as der_decoder + from pyasn1.codec.der.encoder import encode as der_encoder +-from pyasn1.compat.octets import str2octs + + from pyasn1_modules import pem + from pyasn1_modules import rfc5480 +@@ -79,7 +78,7 @@ + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + if extn['extnID'] == rfc3770.id_pe_wlanSSID: +- self.assertIn(str2octs('Example'), extnValue) ++ self.assertIn(b'Example', extnValue) + + if extn['extnID'] == rfc5280.id_ce_extKeyUsage: + self.assertIn(rfc3770.id_kp_eapOverLAN, extnValue) +--- a/tests/test_rfc4073.py ++++ b/tests/test_rfc4073.py +@@ -10,7 +10,6 @@ + + from pyasn1.codec.der.decoder import decode as der_decoder + from pyasn1.codec.der.encoder import encode as der_encoder +-from pyasn1.compat.octets import str2octs + + from pyasn1_modules import pem + from pyasn1_modules import rfc2634 +@@ -131,7 +130,7 @@ + + self.assertIn(next_ci['contentType'], rfc5652.cmsContentTypesMap) + self.assertEqual(rfc5652.id_data, next_ci['contentType']) +- self.assertIn(str2octs('Content-Type: text'), next_ci['content']) ++ self.assertIn(b'Content-Type: text', next_ci['content']) + + for attr in ci['content']['attrs']: + self.assertIn(attr['attrType'], rfc5652.cmsAttributesMap) +--- a/tests/test_rfc4334.py ++++ b/tests/test_rfc4334.py +@@ -10,7 +10,6 @@ + + from pyasn1.codec.der.decoder import decode as der_decoder + from pyasn1.codec.der.encoder import encode as der_encoder +-from pyasn1.compat.octets import str2octs + + from pyasn1_modules import pem + from pyasn1_modules import rfc5280 +@@ -67,7 +66,7 @@ + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + if extn['extnID'] == rfc4334.id_pe_wlanSSID: +- self.assertIn( str2octs('Example'), extnValue) ++ self.assertIn( b'Example', extnValue) + + if extn['extnID'] == rfc5280.id_ce_extKeyUsage: + self.assertIn(rfc4334.id_kp_eapOverLAN, extnValue) +--- a/tests/test_rfc5755.py ++++ b/tests/test_rfc5755.py +@@ -10,7 +10,6 @@ + + from pyasn1.codec.der.decoder import decode as der_decoder + from pyasn1.codec.der.encoder import encode as der_encoder +-from pyasn1.compat.octets import str2octs + + from pyasn1_modules import pem + from pyasn1_modules import rfc5280 +@@ -85,7 +84,7 @@ + count += 1 + if attr['type'] == rfc5755.id_aca_authenticationInfo: + self.assertEqual( +- str2octs('password'), attr['values'][0]['authInfo']) ++ b'password', attr['values'][0]['authInfo']) + + self.assertEqual(5, count) + +--- a/tests/test_rfc6032.py ++++ b/tests/test_rfc6032.py +@@ -10,7 +10,6 @@ + + from pyasn1.codec.der.decoder import decode as der_decoder + from pyasn1.codec.der.encoder import encode as der_encoder +-from pyasn1.compat.octets import str2octs + + from pyasn1_modules import pem + from pyasn1_modules import rfc5652 +@@ -64,7 +63,7 @@ + self.assertFalse(rest) + self.assertTrue(keyid.prettyPrint()) + self.assertEqual(attrVal0, der_encoder(keyid)) +- self.assertEqual(str2octs('ptf-kdc-812374'), keyid) ++ self.assertEqual(b'ptf-kdc-812374', keyid) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.encrypted_key_pkg_pem_text) +@@ -86,8 +85,7 @@ + self.assertNotEqual('0x', attr['attrValues'][0].prettyPrint()[:2]) + + if attr['attrType'] == rfc6032.id_aa_KP_contentDecryptKeyID: +- self.assertEqual(str2octs( +- 'ptf-kdc-812374'), attr['attrValues'][0]) ++ self.assertEqual(b'ptf-kdc-812374', attr['attrValues'][0]) + + + suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) +--- a/tests/test_rfc6120.py ++++ b/tests/test_rfc6120.py +@@ -10,7 +10,6 @@ + + from pyasn1.codec.der.decoder import decode as der_decoder + from pyasn1.codec.der.encoder import encode as der_encoder +-from pyasn1.compat.octets import str2octs + + from pyasn1_modules import pem + from pyasn1_modules import rfc5280 +--- a/tests/test_pem.py ++++ b/tests/test_pem.py +@@ -7,7 +7,6 @@ + import sys + import unittest + +-from pyasn1.compat.octets import ints2octs + from pyasn1_modules import pem + + +@@ -93,7 +92,7 @@ + 24, 102, 241, 236, 50 + ] + +- self.assertEqual(ints2octs(expected), binary) ++ self.assertEqual(bytes(expected), binary) + + + suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) diff --git a/debian/rules b/debian/rules index 03d3965..6cdadba 100755 --- a/debian/rules +++ b/debian/rules @@ -2,4 +2,4 @@ # -*- makefile -*- %: - dh $@ --with python3 --buildsystem=pybuild + dh $@ --buildsystem=pybuild diff --git a/debian/tests/control b/debian/tests/control new file mode 100644 index 0000000..a46bead --- /dev/null +++ b/debian/tests/control @@ -0,0 +1,5 @@ +Tests: unittests +Depends: + @, + python3-all, +Restrictions: allow-stderr diff --git a/debian/tests/unittests b/debian/tests/unittests new file mode 100644 index 0000000..aea4f6c --- /dev/null +++ b/debian/tests/unittests @@ -0,0 +1,7 @@ +#!/bin/sh + +set -e + +for pyvers in $(py3versions -rv 2>/dev/null) ; do + PYTHONPATH=. python$pyvers -m unittest discover -v +done diff --git a/debian/upstream/metadata b/debian/upstream/metadata new file mode 100644 index 0000000..9851e07 --- /dev/null +++ b/debian/upstream/metadata @@ -0,0 +1,5 @@ +--- +Bug-Database: https://github.com/etingof/pyasn1-modules/issues +Bug-Submit: https://github.com/etingof/pyasn1-modules/issues/new +Repository: https://github.com/etingof/pyasn1-modules.git +Repository-Browse: https://github.com/etingof/pyasn1-modules diff --git a/debian/watch b/debian/watch index 226a5dc..ae2be40 100644 --- a/debian/watch +++ b/debian/watch @@ -1,3 +1,3 @@ -version=3 -opts=uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha|b|a)[\-\.]?\d*)$/$1~$2/ \ -http://pypi.debian.net/pyasn1-modules/pyasn1-modules-(.*).tar.gz +version=4 +opts="mode=git,uversionmangle=s/\.0rc/~rc/;s/\.0b1/~b1/;s/\.0b2/~b2/;s/\.0b3/~b3/" \ +https://github.com/pyasn1/pyasn1-modules refs/tags/v(\d[brc\d\.]+) diff --git a/pyasn1_modules.egg-info/PKG-INFO b/pyasn1_modules.egg-info/PKG-INFO deleted file mode 100644 index efb1859..0000000 --- a/pyasn1_modules.egg-info/PKG-INFO +++ /dev/null @@ -1,35 +0,0 @@ -Metadata-Version: 1.1 -Name: pyasn1-modules -Version: 0.2.1 -Summary: A collection of ASN.1-based protocols modules. -Home-page: https://github.com/etingof/pyasn1-modules -Author: Ilya Etingof -Author-email: etingof@gmail.com -License: BSD -Description: A collection of ASN.1 modules expressed in form of pyasn1 classes. Includes protocols PDUs definition (SNMP, LDAP etc.) and various data structures (X.509, PKCS etc.). -Platform: any -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Console -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: Education -Classifier: Intended Audience :: Information Technology -Classifier: Intended Audience :: System Administrators -Classifier: Intended Audience :: Telecommunications Industry -Classifier: License :: OSI Approved :: BSD License -Classifier: Natural Language :: English -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.4 -Classifier: Programming Language :: Python :: 2.5 -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.2 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Topic :: Communications -Classifier: Topic :: System :: Monitoring -Classifier: Topic :: System :: Networking :: Monitoring -Classifier: Topic :: Software Development :: Libraries :: Python Modules diff --git a/pyasn1_modules.egg-info/SOURCES.txt b/pyasn1_modules.egg-info/SOURCES.txt deleted file mode 100644 index 15c3110..0000000 --- a/pyasn1_modules.egg-info/SOURCES.txt +++ /dev/null @@ -1,66 +0,0 @@ -CHANGES.txt -LICENSE.txt -MANIFEST.in -README.md -requirements.txt -setup.cfg -setup.py -pyasn1_modules/__init__.py -pyasn1_modules/pem.py -pyasn1_modules/rfc1155.py -pyasn1_modules/rfc1157.py -pyasn1_modules/rfc1901.py -pyasn1_modules/rfc1902.py -pyasn1_modules/rfc1905.py -pyasn1_modules/rfc2251.py -pyasn1_modules/rfc2314.py -pyasn1_modules/rfc2315.py -pyasn1_modules/rfc2437.py -pyasn1_modules/rfc2459.py -pyasn1_modules/rfc2511.py -pyasn1_modules/rfc2560.py -pyasn1_modules/rfc3279.py -pyasn1_modules/rfc3280.py -pyasn1_modules/rfc3281.py -pyasn1_modules/rfc3412.py -pyasn1_modules/rfc3414.py -pyasn1_modules/rfc3447.py -pyasn1_modules/rfc3852.py -pyasn1_modules/rfc4210.py -pyasn1_modules/rfc4211.py -pyasn1_modules/rfc5208.py -pyasn1_modules/rfc5280.py -pyasn1_modules/rfc5652.py -pyasn1_modules/rfc6402.py -pyasn1_modules.egg-info/PKG-INFO -pyasn1_modules.egg-info/SOURCES.txt -pyasn1_modules.egg-info/dependency_links.txt -pyasn1_modules.egg-info/requires.txt -pyasn1_modules.egg-info/top_level.txt -pyasn1_modules.egg-info/zip-safe -tests/__init__.py -tests/__main__.py -tests/test_rfc2314.py -tests/test_rfc2315.py -tests/test_rfc2437.py -tests/test_rfc2459.py -tests/test_rfc2511.py -tests/test_rfc2560.py -tests/test_rfc4210.py -tests/test_rfc5208.py -tests/test_rfc5280.py -tests/test_rfc5652.py -tools/cmcdump.py -tools/cmpdump.py -tools/crldump.py -tools/crmfdump.py -tools/ocspclient.py -tools/ocspreqdump.py -tools/ocsprspdump.py -tools/pkcs10dump.py -tools/pkcs1dump.py -tools/pkcs7dump.py -tools/pkcs8dump.py -tools/snmpget.py -tools/x509dump-rfc5280.py -tools/x509dump.py \ No newline at end of file diff --git a/pyasn1_modules.egg-info/dependency_links.txt b/pyasn1_modules.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/pyasn1_modules.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/pyasn1_modules.egg-info/requires.txt b/pyasn1_modules.egg-info/requires.txt deleted file mode 100644 index 2c51a6a..0000000 --- a/pyasn1_modules.egg-info/requires.txt +++ /dev/null @@ -1 +0,0 @@ -pyasn1>=0.4.1,<0.5.0 diff --git a/pyasn1_modules.egg-info/top_level.txt b/pyasn1_modules.egg-info/top_level.txt deleted file mode 100644 index 9dad849..0000000 --- a/pyasn1_modules.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -pyasn1_modules diff --git a/pyasn1_modules.egg-info/zip-safe b/pyasn1_modules.egg-info/zip-safe deleted file mode 100644 index 8b13789..0000000 --- a/pyasn1_modules.egg-info/zip-safe +++ /dev/null @@ -1 +0,0 @@ - diff --git a/pyasn1_modules/__init__.py b/pyasn1_modules/__init__.py index d0c5e53..ae0ff01 100644 --- a/pyasn1_modules/__init__.py +++ b/pyasn1_modules/__init__.py @@ -1,2 +1,2 @@ # http://www.python.org/dev/peps/pep-0396/ -__version__ = '0.2.1' +__version__ = '0.4.1' diff --git a/pyasn1_modules/pem.py b/pyasn1_modules/pem.py index 9f16308..29235ab 100644 --- a/pyasn1_modules/pem.py +++ b/pyasn1_modules/pem.py @@ -1,11 +1,10 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # import base64 -import sys stSpam, stHam, stDump = 0, 1, 2 @@ -38,10 +37,7 @@ def readPemBlocksFromFile(fileObj, *markers): else: certLines.append(certLine) if state == stDump: - if sys.version_info[0] <= 2: - substrate = ''.join([base64.b64decode(x) for x in certLines]) - else: - substrate = ''.encode().join([base64.b64decode(x.encode()) for x in certLines]) + substrate = ''.encode().join([base64.b64decode(x.encode()) for x in certLines]) break return idx, substrate @@ -55,10 +51,7 @@ def readPemFromFile(fileObj, def readBase64fromText(text): - if sys.version_info[0] <= 2: - return base64.b64decode(text) - else: - return base64.b64decode(text.encode()) + return base64.b64decode(text.encode()) def readBase64FromFile(fileObj): diff --git a/pyasn1_modules/rfc1155.py b/pyasn1_modules/rfc1155.py index 69c160e..1870234 100644 --- a/pyasn1_modules/rfc1155.py +++ b/pyasn1_modules/rfc1155.py @@ -1,8 +1,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # SNMPv1 message syntax # diff --git a/pyasn1_modules/rfc1157.py b/pyasn1_modules/rfc1157.py index 9e6527b..df49e48 100644 --- a/pyasn1_modules/rfc1157.py +++ b/pyasn1_modules/rfc1157.py @@ -1,8 +1,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # SNMPv1 message syntax # diff --git a/pyasn1_modules/rfc1901.py b/pyasn1_modules/rfc1901.py index 6e8d1f1..658dcb9 100644 --- a/pyasn1_modules/rfc1901.py +++ b/pyasn1_modules/rfc1901.py @@ -1,8 +1,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # SNMPv2c message syntax # diff --git a/pyasn1_modules/rfc1902.py b/pyasn1_modules/rfc1902.py index 7e815d2..063998a 100644 --- a/pyasn1_modules/rfc1902.py +++ b/pyasn1_modules/rfc1902.py @@ -1,8 +1,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # SNMPv2c message syntax # diff --git a/pyasn1_modules/rfc1905.py b/pyasn1_modules/rfc1905.py index 31e4203..435427b 100644 --- a/pyasn1_modules/rfc1905.py +++ b/pyasn1_modules/rfc1905.py @@ -1,8 +1,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # SNMPv2c PDU syntax # @@ -42,7 +42,7 @@ class VarBind(univ.Sequence): class VarBindList(univ.SequenceOf): componentType = VarBind() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint( + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint( 0, max_bindings ) diff --git a/pyasn1_modules/rfc2251.py b/pyasn1_modules/rfc2251.py index a4c07a0..094922c 100644 --- a/pyasn1_modules/rfc2251.py +++ b/pyasn1_modules/rfc2251.py @@ -1,8 +1,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # LDAP message syntax # diff --git a/pyasn1_modules/rfc2314.py b/pyasn1_modules/rfc2314.py index ef6a65b..b0edfe0 100644 --- a/pyasn1_modules/rfc2314.py +++ b/pyasn1_modules/rfc2314.py @@ -1,8 +1,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # PKCS#10 syntax # diff --git a/pyasn1_modules/rfc2315.py b/pyasn1_modules/rfc2315.py index 158aee7..1069fc2 100644 --- a/pyasn1_modules/rfc2315.py +++ b/pyasn1_modules/rfc2315.py @@ -1,8 +1,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # PKCS#7 message syntax # @@ -269,13 +269,13 @@ class DigestInfo(univ.Sequence): class SignedData(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.NamedType('version', Version()), - namedtype.NamedType('digestAlgorithms', DigestAlgorithmIdentifiers()), + namedtype.OptionalNamedType('digestAlgorithms', DigestAlgorithmIdentifiers()), namedtype.NamedType('contentInfo', ContentInfo()), namedtype.OptionalNamedType('certificates', ExtendedCertificatesAndCertificates().subtype( implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), namedtype.OptionalNamedType('crls', CertificateRevocationLists().subtype( implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))), - namedtype.NamedType('signerInfos', SignerInfos()) + namedtype.OptionalNamedType('signerInfos', SignerInfos()) ) @@ -291,4 +291,4 @@ class Data(univ.OctetString): encryptedData: EncryptedData() } -contentTypeMap.update(_contentTypeMapUpdate) \ No newline at end of file +contentTypeMap.update(_contentTypeMapUpdate) diff --git a/pyasn1_modules/rfc2437.py b/pyasn1_modules/rfc2437.py index 4e4113f..88641cf 100644 --- a/pyasn1_modules/rfc2437.py +++ b/pyasn1_modules/rfc2437.py @@ -1,8 +1,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # PKCS#1 syntax # diff --git a/pyasn1_modules/rfc2459.py b/pyasn1_modules/rfc2459.py index 1f78185..57f783e 100644 --- a/pyasn1_modules/rfc2459.py +++ b/pyasn1_modules/rfc2459.py @@ -1,8 +1,11 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Updated by Russ Housley to resolve the TODO regarding the Certificate +# Policies Certificate Extension. +# +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # X.509 message syntax # @@ -354,7 +357,7 @@ class TeletexDomainDefinedAttribute(univ.Sequence): class TeletexDomainDefinedAttributes(univ.SequenceOf): componentType = TeletexDomainDefinedAttribute() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, ub_domain_defined_attributes) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, ub_domain_defined_attributes) terminal_type = univ.Integer(23) @@ -545,7 +548,7 @@ class TeletexOrganizationalUnitName(char.TeletexString): class TeletexOrganizationalUnitNames(univ.SequenceOf): componentType = TeletexOrganizationalUnitName() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, ub_organizational_units) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, ub_organizational_units) teletex_personal_name = univ.Integer(4) @@ -601,7 +604,7 @@ class ExtensionAttribute(univ.Sequence): class ExtensionAttributes(univ.SetOf): componentType = ExtensionAttribute() - subtypeSpec = univ.SetOf.subtypeSpec + constraint.ValueSizeConstraint(1, ub_extension_attributes) + sizeSpec = univ.SetOf.sizeSpec + constraint.ValueSizeConstraint(1, ub_extension_attributes) class BuiltInDomainDefinedAttribute(univ.Sequence): @@ -615,16 +618,16 @@ class BuiltInDomainDefinedAttribute(univ.Sequence): class BuiltInDomainDefinedAttributes(univ.SequenceOf): componentType = BuiltInDomainDefinedAttribute() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, ub_domain_defined_attributes) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, ub_domain_defined_attributes) class OrganizationalUnitName(char.PrintableString): - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, ub_organizational_unit_name_length) + subtypeSpec = char.PrintableString.subtypeSpec + constraint.ValueSizeConstraint(1, ub_organizational_unit_name_length) class OrganizationalUnitNames(univ.SequenceOf): componentType = OrganizationalUnitName() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, ub_organizational_units) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, ub_organizational_units) class PersonalName(univ.Set): @@ -771,7 +774,7 @@ class CRLReason(univ.Enumerated): class CRLNumber(univ.Integer): - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(0, MAX) + subtypeSpec = univ.Integer.subtypeSpec + constraint.ValueSizeConstraint(0, MAX) class BaseCRLNumber(CRLNumber): @@ -796,7 +799,7 @@ class KeyPurposeId(univ.ObjectIdentifier): class ExtKeyUsageSyntax(univ.SequenceOf): componentType = KeyPurposeId() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX) class ReasonFlags(univ.BitString): @@ -925,7 +928,7 @@ class PolicyInformation(univ.Sequence): class CertificatePolicies(univ.SequenceOf): componentType = PolicyInformation() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX) id_ce_policyMappings = univ.ObjectIdentifier('2.5.29.33') @@ -940,7 +943,7 @@ class PolicyMapping(univ.Sequence): class PolicyMappings(univ.SequenceOf): componentType = PolicyMapping() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX) id_ce_privateKeyUsagePeriod = univ.ObjectIdentifier('2.5.29.16') @@ -1024,7 +1027,7 @@ class Attribute(univ.Sequence): class SubjectDirectoryAttributes(univ.SequenceOf): componentType = Attribute() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX) class RelativeDistinguishedName(univ.SetOf): @@ -1077,7 +1080,7 @@ class GeneralName(univ.Choice): class GeneralNames(univ.SequenceOf): componentType = GeneralName() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX) class AccessDescription(univ.Sequence): @@ -1089,7 +1092,7 @@ class AccessDescription(univ.Sequence): class AuthorityInfoAccessSyntax(univ.SequenceOf): componentType = AccessDescription() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX) class AuthorityKeyIdentifier(univ.Sequence): @@ -1125,7 +1128,7 @@ class DistributionPoint(univ.Sequence): class CRLDistPointsSyntax(univ.SequenceOf): componentType = DistributionPoint() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX) class IssuingDistributionPoint(univ.Sequence): @@ -1155,7 +1158,7 @@ class GeneralSubtree(univ.Sequence): class GeneralSubtrees(univ.SequenceOf): componentType = GeneralSubtree() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX) class NameConstraints(univ.Sequence): @@ -1312,8 +1315,7 @@ class CertificateList(univ.Sequence): id_ce_subjectKeyIdentifier: SubjectKeyIdentifier(), id_ce_keyUsage: KeyUsage(), id_ce_privateKeyUsagePeriod: PrivateKeyUsagePeriod(), -# TODO -# id_ce_certificatePolicies: PolicyInformation(), # could be a sequence of concat'ed objects? + id_ce_certificatePolicies: CertificatePolicies(), id_ce_policyMappings: PolicyMappings(), id_ce_subjectAltName: SubjectAltName(), id_ce_issuerAltName: IssuerAltName(), diff --git a/pyasn1_modules/rfc2511.py b/pyasn1_modules/rfc2511.py index b42d1d9..8935cda 100644 --- a/pyasn1_modules/rfc2511.py +++ b/pyasn1_modules/rfc2511.py @@ -1,8 +1,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # X.509 certificate Request Message Format (CRMF) syntax # @@ -109,7 +109,7 @@ class PKIPublicationInfo(univ.Sequence): namedtype.NamedType('action', univ.Integer(namedValues=namedval.NamedValues(('dontPublish', 0), ('pleasePublish', 1)))), namedtype.OptionalNamedType('pubInfos', univ.SequenceOf(componentType=SinglePubInfo()).subtype( - subtypeSpec=constraint.ValueSizeConstraint(1, MAX))) + sizeSpec=constraint.ValueSizeConstraint(1, MAX))) ) @@ -195,7 +195,7 @@ class ProofOfPossession(univ.Choice): class Controls(univ.SequenceOf): componentType = AttributeTypeAndValue() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX) class OptionalValidity(univ.Sequence): @@ -249,10 +249,10 @@ class CertReqMsg(univ.Sequence): namedtype.NamedType('certReq', CertRequest()), namedtype.OptionalNamedType('pop', ProofOfPossession()), namedtype.OptionalNamedType('regInfo', univ.SequenceOf(componentType=AttributeTypeAndValue()).subtype( - subtypeSpec=constraint.ValueSizeConstraint(1, MAX))) + sizeSpec=constraint.ValueSizeConstraint(1, MAX))) ) class CertReqMessages(univ.SequenceOf): componentType = CertReqMsg() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX) diff --git a/pyasn1_modules/rfc2560.py b/pyasn1_modules/rfc2560.py index 47ca4e1..017ac0b 100644 --- a/pyasn1_modules/rfc2560.py +++ b/pyasn1_modules/rfc2560.py @@ -1,8 +1,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # OCSP request/response syntax # diff --git a/pyasn1_modules/rfc2631.py b/pyasn1_modules/rfc2631.py new file mode 100644 index 0000000..44e5371 --- /dev/null +++ b/pyasn1_modules/rfc2631.py @@ -0,0 +1,37 @@ +# +# 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 +# +# Diffie-Hellman Key Agreement +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc2631.txt +# https://www.rfc-editor.org/errata/eid5897 +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import tag +from pyasn1.type import univ + + +class KeySpecificInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('algorithm', univ.ObjectIdentifier()), + namedtype.NamedType('counter', univ.OctetString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(4, 4))) + ) + + +class OtherInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('keyInfo', KeySpecificInfo()), + namedtype.OptionalNamedType('partyAInfo', univ.OctetString().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('suppPubInfo', univ.OctetString().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) + ) diff --git a/pyasn1_modules/rfc2634.py b/pyasn1_modules/rfc2634.py new file mode 100644 index 0000000..2099a4b --- /dev/null +++ b/pyasn1_modules/rfc2634.py @@ -0,0 +1,336 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with assistance from asn1ate v.0.6.0. +# Modified by Russ Housley to add a map for use with opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Enhanced Security Services for S/MIME +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc2634.txt +# + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import namedval +from pyasn1.type import namedtype +from pyasn1.type import tag +from pyasn1.type import univ +from pyasn1.type import useful + +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5280 + +MAX = float('inf') + +ContentType = rfc5652.ContentType + +IssuerAndSerialNumber = rfc5652.IssuerAndSerialNumber + +SubjectKeyIdentifier = rfc5652.SubjectKeyIdentifier + +PolicyInformation = rfc5280.PolicyInformation + +GeneralNames = rfc5280.GeneralNames + +CertificateSerialNumber = rfc5280.CertificateSerialNumber + + +# Signing Certificate Attribute +# Warning: It is better to use SigningCertificateV2 from RFC 5035 + +id_aa_signingCertificate = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.12') + +class Hash(univ.OctetString): + pass # SHA-1 hash of entire certificate; RFC 5035 supports other hash algorithms + + +class IssuerSerial(univ.Sequence): + pass + +IssuerSerial.componentType = namedtype.NamedTypes( + namedtype.NamedType('issuer', GeneralNames()), + namedtype.NamedType('serialNumber', CertificateSerialNumber()) +) + + +class ESSCertID(univ.Sequence): + pass + +ESSCertID.componentType = namedtype.NamedTypes( + namedtype.NamedType('certHash', Hash()), + namedtype.OptionalNamedType('issuerSerial', IssuerSerial()) +) + + +class SigningCertificate(univ.Sequence): + pass + +SigningCertificate.componentType = namedtype.NamedTypes( + namedtype.NamedType('certs', univ.SequenceOf( + componentType=ESSCertID())), + namedtype.OptionalNamedType('policies', univ.SequenceOf( + componentType=PolicyInformation())) +) + + +# Mail List Expansion History Attribute + +id_aa_mlExpandHistory = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.3') + +ub_ml_expansion_history = univ.Integer(64) + + +class EntityIdentifier(univ.Choice): + pass + +EntityIdentifier.componentType = namedtype.NamedTypes( + namedtype.NamedType('issuerAndSerialNumber', IssuerAndSerialNumber()), + namedtype.NamedType('subjectKeyIdentifier', SubjectKeyIdentifier()) +) + + +class MLReceiptPolicy(univ.Choice): + pass + +MLReceiptPolicy.componentType = namedtype.NamedTypes( + namedtype.NamedType('none', univ.Null().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('insteadOf', univ.SequenceOf( + componentType=GeneralNames()).subtype( + sizeSpec=constraint.ValueSizeConstraint(1, MAX)).subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('inAdditionTo', univ.SequenceOf( + componentType=GeneralNames()).subtype( + sizeSpec=constraint.ValueSizeConstraint(1, MAX)).subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) +) + + +class MLData(univ.Sequence): + pass + +MLData.componentType = namedtype.NamedTypes( + namedtype.NamedType('mailListIdentifier', EntityIdentifier()), + namedtype.NamedType('expansionTime', useful.GeneralizedTime()), + namedtype.OptionalNamedType('mlReceiptPolicy', MLReceiptPolicy()) +) + +class MLExpansionHistory(univ.SequenceOf): + pass + +MLExpansionHistory.componentType = MLData() +MLExpansionHistory.sizeSpec = constraint.ValueSizeConstraint(1, ub_ml_expansion_history) + + +# ESS Security Label Attribute + +id_aa_securityLabel = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.2') + +ub_privacy_mark_length = univ.Integer(128) + +ub_security_categories = univ.Integer(64) + +ub_integer_options = univ.Integer(256) + + +class ESSPrivacyMark(univ.Choice): + pass + +ESSPrivacyMark.componentType = namedtype.NamedTypes( + namedtype.NamedType('pString', char.PrintableString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, ub_privacy_mark_length))), + namedtype.NamedType('utf8String', char.UTF8String().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, MAX))) +) + + +class SecurityClassification(univ.Integer): + pass + +SecurityClassification.subtypeSpec=constraint.ValueRangeConstraint(0, ub_integer_options) + +SecurityClassification.namedValues = namedval.NamedValues( + ('unmarked', 0), + ('unclassified', 1), + ('restricted', 2), + ('confidential', 3), + ('secret', 4), + ('top-secret', 5) +) + + +class SecurityPolicyIdentifier(univ.ObjectIdentifier): + pass + + +class SecurityCategory(univ.Sequence): + pass + +SecurityCategory.componentType = namedtype.NamedTypes( + namedtype.NamedType('type', univ.ObjectIdentifier().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('value', univ.Any().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class SecurityCategories(univ.SetOf): + pass + +SecurityCategories.componentType = SecurityCategory() +SecurityCategories.sizeSpec = constraint.ValueSizeConstraint(1, ub_security_categories) + + +class ESSSecurityLabel(univ.Set): + pass + +ESSSecurityLabel.componentType = namedtype.NamedTypes( + namedtype.NamedType('security-policy-identifier', SecurityPolicyIdentifier()), + namedtype.OptionalNamedType('security-classification', SecurityClassification()), + namedtype.OptionalNamedType('privacy-mark', ESSPrivacyMark()), + namedtype.OptionalNamedType('security-categories', SecurityCategories()) +) + + +# Equivalent Labels Attribute + +id_aa_equivalentLabels = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.9') + +class EquivalentLabels(univ.SequenceOf): + pass + +EquivalentLabels.componentType = ESSSecurityLabel() + + +# Content Identifier Attribute + +id_aa_contentIdentifier = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.7') + +class ContentIdentifier(univ.OctetString): + pass + + +# Content Reference Attribute + +id_aa_contentReference = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.10') + +class ContentReference(univ.Sequence): + pass + +ContentReference.componentType = namedtype.NamedTypes( + namedtype.NamedType('contentType', ContentType()), + namedtype.NamedType('signedContentIdentifier', ContentIdentifier()), + namedtype.NamedType('originatorSignatureValue', univ.OctetString()) +) + + +# Message Signature Digest Attribute + +id_aa_msgSigDigest = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.5') + +class MsgSigDigest(univ.OctetString): + pass + + +# Content Hints Attribute + +id_aa_contentHint = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.4') + +class ContentHints(univ.Sequence): + pass + +ContentHints.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('contentDescription', char.UTF8String().subtype(subtypeSpec=constraint.ValueSizeConstraint(1, MAX))), + namedtype.NamedType('contentType', ContentType()) +) + + +# Receipt Request Attribute + +class AllOrFirstTier(univ.Integer): + pass + +AllOrFirstTier.namedValues = namedval.NamedValues( + ('allReceipts', 0), + ('firstTierRecipients', 1) +) + + +class ReceiptsFrom(univ.Choice): + pass + +ReceiptsFrom.componentType = namedtype.NamedTypes( + namedtype.NamedType('allOrFirstTier', AllOrFirstTier().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('receiptList', univ.SequenceOf( + componentType=GeneralNames()).subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +id_aa_receiptRequest = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.1') + +ub_receiptsTo = univ.Integer(16) + +class ReceiptRequest(univ.Sequence): + pass + +ReceiptRequest.componentType = namedtype.NamedTypes( + namedtype.NamedType('signedContentIdentifier', ContentIdentifier()), + namedtype.NamedType('receiptsFrom', ReceiptsFrom()), + namedtype.NamedType('receiptsTo', univ.SequenceOf(componentType=GeneralNames()).subtype(sizeSpec=constraint.ValueSizeConstraint(1, ub_receiptsTo))) +) + +# Receipt Content Type + +class ESSVersion(univ.Integer): + pass + +ESSVersion.namedValues = namedval.NamedValues( + ('v1', 1) +) + + +id_ct_receipt = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.1') + +class Receipt(univ.Sequence): + pass + +Receipt.componentType = namedtype.NamedTypes( + namedtype.NamedType('version', ESSVersion()), + namedtype.NamedType('contentType', ContentType()), + namedtype.NamedType('signedContentIdentifier', ContentIdentifier()), + namedtype.NamedType('originatorSignatureValue', univ.OctetString()) +) + + +# Map of Attribute Type to the Attribute structure is added to the +# ones that are in rfc5652.py + +_cmsAttributesMapUpdate = { + id_aa_signingCertificate: SigningCertificate(), + id_aa_mlExpandHistory: MLExpansionHistory(), + id_aa_securityLabel: ESSSecurityLabel(), + id_aa_equivalentLabels: EquivalentLabels(), + id_aa_contentIdentifier: ContentIdentifier(), + id_aa_contentReference: ContentReference(), + id_aa_msgSigDigest: MsgSigDigest(), + id_aa_contentHint: ContentHints(), + id_aa_receiptRequest: ReceiptRequest(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) + + +# Map of Content Type OIDs to Content Types is added to the +# ones that are in rfc5652.py + +_cmsContentTypesMapUpdate = { + id_ct_receipt: Receipt(), +} + +rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate) diff --git a/pyasn1_modules/rfc2876.py b/pyasn1_modules/rfc2876.py new file mode 100644 index 0000000..04c402b --- /dev/null +++ b/pyasn1_modules/rfc2876.py @@ -0,0 +1,56 @@ +# +# 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 +# +# KEA and SKIPJACK Algorithms in CMS +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc2876.txt +# + +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5751 + + +id_fortezzaConfidentialityAlgorithm = univ.ObjectIdentifier('2.16.840.1.101.2.1.1.4') + + +id_fortezzaWrap80 = univ.ObjectIdentifier('2.16.840.1.101.2.1.1.23') + + +id_kEAKeyEncryptionAlgorithm = univ.ObjectIdentifier('2.16.840.1.101.2.1.1.24') + + +id_keyExchangeAlgorithm = univ.ObjectIdentifier('2.16.840.1.101.2.1.1.22') + + +class Skipjack_Parm(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('initialization-vector', univ.OctetString()) + ) + + +# Update the Algorithm Identifier map in rfc5280.py. + +_algorithmIdentifierMapUpdate = { + id_fortezzaConfidentialityAlgorithm: Skipjack_Parm(), + id_kEAKeyEncryptionAlgorithm: rfc5280.AlgorithmIdentifier(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) + + +# Update the SMIMECapabilities Attribute map in rfc5751.py + +_smimeCapabilityMapUpdate = { + id_kEAKeyEncryptionAlgorithm: rfc5280.AlgorithmIdentifier(), +} + +rfc5751.smimeCapabilityMap.update(_smimeCapabilityMapUpdate) diff --git a/pyasn1_modules/rfc2985.py b/pyasn1_modules/rfc2985.py new file mode 100644 index 0000000..75bccf0 --- /dev/null +++ b/pyasn1_modules/rfc2985.py @@ -0,0 +1,588 @@ +# +# 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 +# +# PKCS#9: Selected Attribute Types (Version 2.0) +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc2985.txt +# + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import opentype +from pyasn1.type import tag +from pyasn1.type import univ +from pyasn1.type import useful + +from pyasn1_modules import rfc7292 +from pyasn1_modules import rfc5958 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5280 + + +def _OID(*components): + output = [] + for x in tuple(components): + if isinstance(x, univ.ObjectIdentifier): + output.extend(list(x)) + else: + output.append(int(x)) + + return univ.ObjectIdentifier(output) + + +MAX = float('inf') + + +# Imports from RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + +Attribute = rfc5280.Attribute + +EmailAddress = rfc5280.EmailAddress + +Extensions = rfc5280.Extensions + +Time = rfc5280.Time + +X520countryName = rfc5280.X520countryName + +X520SerialNumber = rfc5280.X520SerialNumber + + +# Imports from RFC 5652 + +ContentInfo = rfc5652.ContentInfo + +ContentType = rfc5652.ContentType + +Countersignature = rfc5652.Countersignature + +MessageDigest = rfc5652.MessageDigest + +SignerInfo = rfc5652.SignerInfo + +SigningTime = rfc5652.SigningTime + + +# Imports from RFC 5958 + +EncryptedPrivateKeyInfo = rfc5958.EncryptedPrivateKeyInfo + + +# Imports from RFC 7292 + +PFX = rfc7292.PFX + + +# TODO: +# Need a place to import PKCS15Token; it does not yet appear in an RFC + + +# SingleAttribute is the same as Attribute in RFC 5280, except that the +# attrValues SET must have one and only one member + +class AttributeType(univ.ObjectIdentifier): + pass + + +class AttributeValue(univ.Any): + pass + + +class AttributeValues(univ.SetOf): + pass + +AttributeValues.componentType = AttributeValue() + + +class SingleAttributeValues(univ.SetOf): + pass + +SingleAttributeValues.componentType = AttributeValue() + + +class SingleAttribute(univ.Sequence): + pass + +SingleAttribute.componentType = namedtype.NamedTypes( + namedtype.NamedType('type', AttributeType()), + namedtype.NamedType('values', + AttributeValues().subtype(sizeSpec=constraint.ValueSizeConstraint(1, 1)), + openType=opentype.OpenType('type', rfc5280.certificateAttributesMap) + ) +) + + +# CMSAttribute is the same as Attribute in RFC 5652, and CMSSingleAttribute +# is the companion where the attrValues SET must have one and only one member + +CMSAttribute = rfc5652.Attribute + + +class CMSSingleAttribute(univ.Sequence): + pass + +CMSSingleAttribute.componentType = namedtype.NamedTypes( + namedtype.NamedType('attrType', AttributeType()), + namedtype.NamedType('attrValues', + AttributeValues().subtype(sizeSpec=constraint.ValueSizeConstraint(1, 1)), + openType=opentype.OpenType('attrType', rfc5652.cmsAttributesMap) + ) +) + + +# DirectoryString is the same as RFC 5280, except the length is limited to 255 + +class DirectoryString(univ.Choice): + pass + +DirectoryString.componentType = namedtype.NamedTypes( + namedtype.NamedType('teletexString', char.TeletexString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, 255))), + namedtype.NamedType('printableString', char.PrintableString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, 255))), + namedtype.NamedType('universalString', char.UniversalString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, 255))), + namedtype.NamedType('utf8String', char.UTF8String().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, 255))), + namedtype.NamedType('bmpString', char.BMPString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, 255))) +) + + +# PKCS9String is DirectoryString with an additional choice of IA5String, +# and the SIZE is limited to 255 + +class PKCS9String(univ.Choice): + pass + +PKCS9String.componentType = namedtype.NamedTypes( + namedtype.NamedType('ia5String', char.IA5String().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, 255))), + namedtype.NamedType('directoryString', DirectoryString()) +) + + +# Upper Bounds + +pkcs_9_ub_pkcs9String = univ.Integer(255) + +pkcs_9_ub_challengePassword = univ.Integer(pkcs_9_ub_pkcs9String) + +pkcs_9_ub_emailAddress = univ.Integer(pkcs_9_ub_pkcs9String) + +pkcs_9_ub_friendlyName = univ.Integer(pkcs_9_ub_pkcs9String) + +pkcs_9_ub_match = univ.Integer(pkcs_9_ub_pkcs9String) + +pkcs_9_ub_signingDescription = univ.Integer(pkcs_9_ub_pkcs9String) + +pkcs_9_ub_unstructuredAddress = univ.Integer(pkcs_9_ub_pkcs9String) + +pkcs_9_ub_unstructuredName = univ.Integer(pkcs_9_ub_pkcs9String) + + +ub_name = univ.Integer(32768) + +pkcs_9_ub_placeOfBirth = univ.Integer(ub_name) + +pkcs_9_ub_pseudonym = univ.Integer(ub_name) + + +# Object Identifier Arcs + +ietf_at = _OID(1, 3, 6, 1, 5, 5, 7, 9) + +id_at = _OID(2, 5, 4) + +pkcs_9 = _OID(1, 2, 840, 113549, 1, 9) + +pkcs_9_mo = _OID(pkcs_9, 0) + +smime = _OID(pkcs_9, 16) + +certTypes = _OID(pkcs_9, 22) + +crlTypes = _OID(pkcs_9, 23) + +pkcs_9_oc = _OID(pkcs_9, 24) + +pkcs_9_at = _OID(pkcs_9, 25) + +pkcs_9_sx = _OID(pkcs_9, 26) + +pkcs_9_mr = _OID(pkcs_9, 27) + + +# Object Identifiers for Syntaxes for use with LDAP-accessible directories + +pkcs_9_sx_pkcs9String = _OID(pkcs_9_sx, 1) + +pkcs_9_sx_signingTime = _OID(pkcs_9_sx, 2) + + +# Object Identifiers for object classes + +pkcs_9_oc_pkcsEntity = _OID(pkcs_9_oc, 1) + +pkcs_9_oc_naturalPerson = _OID(pkcs_9_oc, 2) + + +# Object Identifiers for matching rules + +pkcs_9_mr_caseIgnoreMatch = _OID(pkcs_9_mr, 1) + +pkcs_9_mr_signingTimeMatch = _OID(pkcs_9_mr, 2) + + +# PKCS #7 PDU + +pkcs_9_at_pkcs7PDU = _OID(pkcs_9_at, 5) + +pKCS7PDU = Attribute() +pKCS7PDU['type'] = pkcs_9_at_pkcs7PDU +pKCS7PDU['values'][0] = ContentInfo() + + +# PKCS #12 token + +pkcs_9_at_userPKCS12 = _OID(2, 16, 840, 1, 113730, 3, 1, 216) + +userPKCS12 = Attribute() +userPKCS12['type'] = pkcs_9_at_userPKCS12 +userPKCS12['values'][0] = PFX() + + +# PKCS #15 token + +pkcs_9_at_pkcs15Token = _OID(pkcs_9_at, 1) + +# TODO: Once PKCS15Token can be imported, this can be included +# +# pKCS15Token = Attribute() +# userPKCS12['type'] = pkcs_9_at_pkcs15Token +# userPKCS12['values'][0] = PKCS15Token() + + +# PKCS #8 encrypted private key information + +pkcs_9_at_encryptedPrivateKeyInfo = _OID(pkcs_9_at, 2) + +encryptedPrivateKeyInfo = Attribute() +encryptedPrivateKeyInfo['type'] = pkcs_9_at_encryptedPrivateKeyInfo +encryptedPrivateKeyInfo['values'][0] = EncryptedPrivateKeyInfo() + + +# Electronic-mail address + +pkcs_9_at_emailAddress = rfc5280.id_emailAddress + +emailAddress = Attribute() +emailAddress['type'] = pkcs_9_at_emailAddress +emailAddress['values'][0] = EmailAddress() + + +# Unstructured name + +pkcs_9_at_unstructuredName = _OID(pkcs_9, 2) + +unstructuredName = Attribute() +unstructuredName['type'] = pkcs_9_at_unstructuredName +unstructuredName['values'][0] = PKCS9String() + + +# Unstructured address + +pkcs_9_at_unstructuredAddress = _OID(pkcs_9, 8) + +unstructuredAddress = Attribute() +unstructuredAddress['type'] = pkcs_9_at_unstructuredAddress +unstructuredAddress['values'][0] = DirectoryString() + + +# Date of birth + +pkcs_9_at_dateOfBirth = _OID(ietf_at, 1) + +dateOfBirth = SingleAttribute() +dateOfBirth['type'] = pkcs_9_at_dateOfBirth +dateOfBirth['values'][0] = useful.GeneralizedTime() + + +# Place of birth + +pkcs_9_at_placeOfBirth = _OID(ietf_at, 2) + +placeOfBirth = SingleAttribute() +placeOfBirth['type'] = pkcs_9_at_placeOfBirth +placeOfBirth['values'][0] = DirectoryString() + + +# Gender + +class GenderString(char.PrintableString): + pass + +GenderString.subtypeSpec = constraint.ValueSizeConstraint(1, 1) +GenderString.subtypeSpec = constraint.SingleValueConstraint("M", "F", "m", "f") + + +pkcs_9_at_gender = _OID(ietf_at, 3) + +gender = SingleAttribute() +gender['type'] = pkcs_9_at_gender +gender['values'][0] = GenderString() + + +# Country of citizenship + +pkcs_9_at_countryOfCitizenship = _OID(ietf_at, 4) + +countryOfCitizenship = Attribute() +countryOfCitizenship['type'] = pkcs_9_at_countryOfCitizenship +countryOfCitizenship['values'][0] = X520countryName() + + +# Country of residence + +pkcs_9_at_countryOfResidence = _OID(ietf_at, 5) + +countryOfResidence = Attribute() +countryOfResidence['type'] = pkcs_9_at_countryOfResidence +countryOfResidence['values'][0] = X520countryName() + + +# Pseudonym + +id_at_pseudonym = _OID(2, 5, 4, 65) + +pseudonym = Attribute() +pseudonym['type'] = id_at_pseudonym +pseudonym['values'][0] = DirectoryString() + + +# Serial number + +id_at_serialNumber = rfc5280.id_at_serialNumber + +serialNumber = Attribute() +serialNumber['type'] = id_at_serialNumber +serialNumber['values'][0] = X520SerialNumber() + + +# Content type + +pkcs_9_at_contentType = rfc5652.id_contentType + +contentType = CMSSingleAttribute() +contentType['attrType'] = pkcs_9_at_contentType +contentType['attrValues'][0] = ContentType() + + +# Message digest + +pkcs_9_at_messageDigest = rfc5652.id_messageDigest + +messageDigest = CMSSingleAttribute() +messageDigest['attrType'] = pkcs_9_at_messageDigest +messageDigest['attrValues'][0] = MessageDigest() + + +# Signing time + +pkcs_9_at_signingTime = rfc5652.id_signingTime + +signingTime = CMSSingleAttribute() +signingTime['attrType'] = pkcs_9_at_signingTime +signingTime['attrValues'][0] = SigningTime() + + +# Random nonce + +class RandomNonce(univ.OctetString): + pass + +RandomNonce.subtypeSpec = constraint.ValueSizeConstraint(4, MAX) + + +pkcs_9_at_randomNonce = _OID(pkcs_9_at, 3) + +randomNonce = CMSSingleAttribute() +randomNonce['attrType'] = pkcs_9_at_randomNonce +randomNonce['attrValues'][0] = RandomNonce() + + +# Sequence number + +class SequenceNumber(univ.Integer): + pass + +SequenceNumber.subtypeSpec = constraint.ValueRangeConstraint(1, MAX) + + +pkcs_9_at_sequenceNumber = _OID(pkcs_9_at, 4) + +sequenceNumber = CMSSingleAttribute() +sequenceNumber['attrType'] = pkcs_9_at_sequenceNumber +sequenceNumber['attrValues'][0] = SequenceNumber() + + +# Countersignature + +pkcs_9_at_counterSignature = rfc5652.id_countersignature + +counterSignature = CMSAttribute() +counterSignature['attrType'] = pkcs_9_at_counterSignature +counterSignature['attrValues'][0] = Countersignature() + + +# Challenge password + +pkcs_9_at_challengePassword = _OID(pkcs_9, 7) + +challengePassword = SingleAttribute() +challengePassword['type'] = pkcs_9_at_challengePassword +challengePassword['values'][0] = DirectoryString() + + +# Extension request + +class ExtensionRequest(Extensions): + pass + + +pkcs_9_at_extensionRequest = _OID(pkcs_9, 14) + +extensionRequest = SingleAttribute() +extensionRequest['type'] = pkcs_9_at_extensionRequest +extensionRequest['values'][0] = ExtensionRequest() + + +# Extended-certificate attributes (deprecated) + +class AttributeSet(univ.SetOf): + pass + +AttributeSet.componentType = Attribute() + + +pkcs_9_at_extendedCertificateAttributes = _OID(pkcs_9, 9) + +extendedCertificateAttributes = SingleAttribute() +extendedCertificateAttributes['type'] = pkcs_9_at_extendedCertificateAttributes +extendedCertificateAttributes['values'][0] = AttributeSet() + + +# Friendly name + +class FriendlyName(char.BMPString): + pass + +FriendlyName.subtypeSpec = constraint.ValueSizeConstraint(1, pkcs_9_ub_friendlyName) + + +pkcs_9_at_friendlyName = _OID(pkcs_9, 20) + +friendlyName = SingleAttribute() +friendlyName['type'] = pkcs_9_at_friendlyName +friendlyName['values'][0] = FriendlyName() + + +# Local key identifier + +pkcs_9_at_localKeyId = _OID(pkcs_9, 21) + +localKeyId = SingleAttribute() +localKeyId['type'] = pkcs_9_at_localKeyId +localKeyId['values'][0] = univ.OctetString() + + +# Signing description + +pkcs_9_at_signingDescription = _OID(pkcs_9, 13) + +signingDescription = CMSSingleAttribute() +signingDescription['attrType'] = pkcs_9_at_signingDescription +signingDescription['attrValues'][0] = DirectoryString() + + +# S/MIME capabilities + +class SMIMECapability(AlgorithmIdentifier): + pass + + +class SMIMECapabilities(univ.SequenceOf): + pass + +SMIMECapabilities.componentType = SMIMECapability() + + +pkcs_9_at_smimeCapabilities = _OID(pkcs_9, 15) + +smimeCapabilities = CMSSingleAttribute() +smimeCapabilities['attrType'] = pkcs_9_at_smimeCapabilities +smimeCapabilities['attrValues'][0] = SMIMECapabilities() + + +# Certificate Attribute Map + +_certificateAttributesMapUpdate = { + # Attribute types for use with the "pkcsEntity" object class + pkcs_9_at_pkcs7PDU: ContentInfo(), + pkcs_9_at_userPKCS12: PFX(), + # TODO: Once PKCS15Token can be imported, this can be included + # pkcs_9_at_pkcs15Token: PKCS15Token(), + pkcs_9_at_encryptedPrivateKeyInfo: EncryptedPrivateKeyInfo(), + # Attribute types for use with the "naturalPerson" object class + pkcs_9_at_emailAddress: EmailAddress(), + pkcs_9_at_unstructuredName: PKCS9String(), + pkcs_9_at_unstructuredAddress: DirectoryString(), + pkcs_9_at_dateOfBirth: useful.GeneralizedTime(), + pkcs_9_at_placeOfBirth: DirectoryString(), + pkcs_9_at_gender: GenderString(), + pkcs_9_at_countryOfCitizenship: X520countryName(), + pkcs_9_at_countryOfResidence: X520countryName(), + id_at_pseudonym: DirectoryString(), + id_at_serialNumber: X520SerialNumber(), + # Attribute types for use with PKCS #10 certificate requests + pkcs_9_at_challengePassword: DirectoryString(), + pkcs_9_at_extensionRequest: ExtensionRequest(), + pkcs_9_at_extendedCertificateAttributes: AttributeSet(), +} + +rfc5280.certificateAttributesMap.update(_certificateAttributesMapUpdate) + + +# CMS Attribute Map + +# Note: pkcs_9_at_smimeCapabilities is not included in the map because +# the definition in RFC 5751 is preferred, which produces the same +# encoding, but it allows different parameters for SMIMECapability +# and AlgorithmIdentifier. + +_cmsAttributesMapUpdate = { + # Attribute types for use in PKCS #7 data (a.k.a. CMS) + pkcs_9_at_contentType: ContentType(), + pkcs_9_at_messageDigest: MessageDigest(), + pkcs_9_at_signingTime: SigningTime(), + pkcs_9_at_randomNonce: RandomNonce(), + pkcs_9_at_sequenceNumber: SequenceNumber(), + pkcs_9_at_counterSignature: Countersignature(), + # Attributes for use in PKCS #12 "PFX" PDUs or PKCS #15 tokens + pkcs_9_at_friendlyName: FriendlyName(), + pkcs_9_at_localKeyId: univ.OctetString(), + pkcs_9_at_signingDescription: DirectoryString(), + # pkcs_9_at_smimeCapabilities: SMIMECapabilities(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) diff --git a/pyasn1_modules/rfc2986.py b/pyasn1_modules/rfc2986.py new file mode 100644 index 0000000..309637d --- /dev/null +++ b/pyasn1_modules/rfc2986.py @@ -0,0 +1,75 @@ +# coding: utf-8 +# +# This file is part of pyasn1-modules software. +# +# Created by Joel Johnson with asn1ate tool. +# Modified by Russ Housley to add support for opentypes by importing +# definitions from rfc5280 so that the same maps are used. +# +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html +# +# PKCS #10: Certification Request Syntax Specification +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc2986.txt +# +from pyasn1.type import namedtype +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + +MAX = float('inf') + + +AttributeType = rfc5280.AttributeType + +AttributeValue = rfc5280.AttributeValue + +AttributeTypeAndValue = rfc5280.AttributeTypeAndValue + +Attribute = rfc5280.Attribute + +RelativeDistinguishedName = rfc5280.RelativeDistinguishedName + +RDNSequence = rfc5280.RDNSequence + +Name = rfc5280.Name + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + +SubjectPublicKeyInfo = rfc5280.SubjectPublicKeyInfo + + +class Attributes(univ.SetOf): + pass + + +Attributes.componentType = Attribute() + + +class CertificationRequestInfo(univ.Sequence): + pass + + +CertificationRequestInfo.componentType = namedtype.NamedTypes( + namedtype.NamedType('version', univ.Integer()), + namedtype.NamedType('subject', Name()), + namedtype.NamedType('subjectPKInfo', SubjectPublicKeyInfo()), + namedtype.NamedType('attributes', + Attributes().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0)) + ) +) + + +class CertificationRequest(univ.Sequence): + pass + + +CertificationRequest.componentType = namedtype.NamedTypes( + namedtype.NamedType('certificationRequestInfo', CertificationRequestInfo()), + namedtype.NamedType('signatureAlgorithm', AlgorithmIdentifier()), + namedtype.NamedType('signature', univ.BitString()) +) diff --git a/pyasn1_modules/rfc3058.py b/pyasn1_modules/rfc3058.py new file mode 100644 index 0000000..725de82 --- /dev/null +++ b/pyasn1_modules/rfc3058.py @@ -0,0 +1,42 @@ +# +# 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 +# +# IDEA Encryption Algorithm in CMS +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc3058.txt +# https://www.rfc-editor.org/errata/eid5913 +# + +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +id_IDEA_CBC = univ.ObjectIdentifier('1.3.6.1.4.1.188.7.1.1.2') + + +id_alg_CMSIDEAwrap = univ.ObjectIdentifier('1.3.6.1.4.1.188.7.1.1.6') + + +class IDEA_CBCPar(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('iv', univ.OctetString()) + # exactly 8 octets, when present + ) + + +# Update the Algorithm Identifier map in rfc5280.py. + +_algorithmIdentifierMapUpdate = { + id_IDEA_CBC: IDEA_CBCPar(), + id_alg_CMSIDEAwrap: univ.Null("") +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc3114.py b/pyasn1_modules/rfc3114.py new file mode 100644 index 0000000..badcb1f --- /dev/null +++ b/pyasn1_modules/rfc3114.py @@ -0,0 +1,77 @@ +# +# 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 +# +# TEST Company Classification Policies +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc3114.txt +# + +from pyasn1.type import char +from pyasn1.type import namedval +from pyasn1.type import univ + +from pyasn1_modules import rfc5755 + + +id_smime = univ.ObjectIdentifier((1, 2, 840, 113549, 1, 9, 16, )) + +id_tsp = id_smime + (7, ) + +id_tsp_TEST_Amoco = id_tsp + (1, ) + +class Amoco_SecurityClassification(univ.Integer): + namedValues = namedval.NamedValues( + ('amoco-general', 6), + ('amoco-confidential', 7), + ('amoco-highly-confidential', 8) + ) + + +id_tsp_TEST_Caterpillar = id_tsp + (2, ) + +class Caterpillar_SecurityClassification(univ.Integer): + namedValues = namedval.NamedValues( + ('caterpillar-public', 6), + ('caterpillar-green', 7), + ('caterpillar-yellow', 8), + ('caterpillar-red', 9) + ) + + +id_tsp_TEST_Whirlpool = id_tsp + (3, ) + +class Whirlpool_SecurityClassification(univ.Integer): + namedValues = namedval.NamedValues( + ('whirlpool-public', 6), + ('whirlpool-internal', 7), + ('whirlpool-confidential', 8) + ) + + +id_tsp_TEST_Whirlpool_Categories = id_tsp + (4, ) + +class SecurityCategoryValues(univ.SequenceOf): + componentType = char.UTF8String() + +# Example SecurityCategoryValues: "LAW DEPARTMENT USE ONLY" +# Example SecurityCategoryValues: "HUMAN RESOURCES USE ONLY" + + +# Also, the privacy mark in the security label can contain a string, +# such as: "ATTORNEY-CLIENT PRIVILEGED INFORMATION" + + +# Map of security category type OIDs to security category added +# to the ones that are in rfc5755.py + +_securityCategoryMapUpdate = { + id_tsp_TEST_Whirlpool_Categories: SecurityCategoryValues(), +} + +rfc5755.securityCategoryMap.update(_securityCategoryMapUpdate) diff --git a/pyasn1_modules/rfc3125.py b/pyasn1_modules/rfc3125.py new file mode 100644 index 0000000..00ff9bf --- /dev/null +++ b/pyasn1_modules/rfc3125.py @@ -0,0 +1,469 @@ +# +# 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 +# +# Electronic Signature Policies +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc3125.txt +# https://www.rfc-editor.org/errata/eid5901 +# https://www.rfc-editor.org/errata/eid5902 +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import tag +from pyasn1.type import useful +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + +MAX = float('inf') + + +# Imports from RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + +Attribute = rfc5280.Attribute + +AttributeType = rfc5280.AttributeType + +AttributeTypeAndValue = rfc5280.AttributeTypeAndValue + +AttributeValue = rfc5280.AttributeValue + +Certificate = rfc5280.Certificate + +CertificateList = rfc5280.CertificateList + +DirectoryString = rfc5280.DirectoryString + +GeneralName = rfc5280.GeneralName + +GeneralNames = rfc5280.GeneralNames + +Name = rfc5280.Name + +PolicyInformation = rfc5280.PolicyInformation + + +# Electronic Signature Policies + +class CertPolicyId(univ.ObjectIdentifier): + pass + + +class AcceptablePolicySet(univ.SequenceOf): + componentType = CertPolicyId() + + +class SignPolExtn(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('extnID', univ.ObjectIdentifier()), + namedtype.NamedType('extnValue', univ.OctetString()) + ) + + +class SignPolExtensions(univ.SequenceOf): + componentType = SignPolExtn() + + +class AlgAndLength(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('algID', univ.ObjectIdentifier()), + namedtype.OptionalNamedType('minKeyLength', univ.Integer()), + namedtype.OptionalNamedType('other', SignPolExtensions()) + ) + + +class AlgorithmConstraints(univ.SequenceOf): + componentType = AlgAndLength() + + +class AlgorithmConstraintSet(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('signerAlgorithmConstraints', + AlgorithmConstraints().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('eeCertAlgorithmConstraints', + AlgorithmConstraints().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('caCertAlgorithmConstraints', + AlgorithmConstraints().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.OptionalNamedType('aaCertAlgorithmConstraints', + AlgorithmConstraints().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.OptionalNamedType('tsaCertAlgorithmConstraints', + AlgorithmConstraints().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 4))) + ) + + +class AttributeValueConstraints(univ.SequenceOf): + componentType = AttributeTypeAndValue() + + +class AttributeTypeConstraints(univ.SequenceOf): + componentType = AttributeType() + + +class AttributeConstraints(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('attributeTypeConstarints', + AttributeTypeConstraints().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('attributeValueConstarints', + AttributeValueConstraints().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))) + ) + + +class HowCertAttribute(univ.Enumerated): + namedValues = namedval.NamedValues( + ('claimedAttribute', 0), + ('certifiedAttribtes', 1), + ('either', 2) + ) + + +class SkipCerts(univ.Integer): + subtypeSpec = constraint.ValueRangeConstraint(0, MAX) + + +class PolicyConstraints(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('requireExplicitPolicy', + SkipCerts().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('inhibitPolicyMapping', + SkipCerts().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))) + ) + + +class BaseDistance(univ.Integer): + subtypeSpec = constraint.ValueRangeConstraint(0, MAX) + + +class GeneralSubtree(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('base', GeneralName()), + namedtype.DefaultedNamedType('minimum', + BaseDistance().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0)).subtype( + value=0)), + namedtype.OptionalNamedType('maximum', + BaseDistance().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))) + ) + + +class GeneralSubtrees(univ.SequenceOf): + componentType = GeneralSubtree() + subtypeSpec = constraint.ValueSizeConstraint(1, MAX) + + +class NameConstraints(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('permittedSubtrees', + GeneralSubtrees().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('excludedSubtrees', + GeneralSubtrees().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))) + ) + + +class PathLenConstraint(univ.Integer): + subtypeSpec = constraint.ValueRangeConstraint(0, MAX) + + +class CertificateTrustPoint(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('trustpoint', Certificate()), + namedtype.OptionalNamedType('pathLenConstraint', + PathLenConstraint().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('acceptablePolicySet', + AcceptablePolicySet().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('nameConstraints', + NameConstraints().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 2))), + namedtype.OptionalNamedType('policyConstraints', + PolicyConstraints().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 3))) + ) + + +class CertificateTrustTrees(univ.SequenceOf): + componentType = CertificateTrustPoint() + + +class EnuRevReq(univ.Enumerated): + namedValues = namedval.NamedValues( + ('clrCheck', 0), + ('ocspCheck', 1), + ('bothCheck', 2), + ('eitherCheck', 3), + ('noCheck', 4), + ('other', 5) + ) + + +class RevReq(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('enuRevReq', EnuRevReq()), + namedtype.OptionalNamedType('exRevReq', SignPolExtensions()) + ) + + +class CertRevReq(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('endCertRevReq', RevReq()), + namedtype.NamedType('caCerts', + RevReq().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 0))) + ) + + +class AttributeTrustCondition(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('attributeMandated', univ.Boolean()), + namedtype.NamedType('howCertAttribute', HowCertAttribute()), + namedtype.OptionalNamedType('attrCertificateTrustTrees', + CertificateTrustTrees().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('attrRevReq', + CertRevReq().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 1))), + namedtype.OptionalNamedType('attributeConstraints', + AttributeConstraints().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 2))) + ) + + +class CMSAttrs(univ.SequenceOf): + componentType = univ.ObjectIdentifier() + + +class CertInfoReq(univ.Enumerated): + namedValues = namedval.NamedValues( + ('none', 0), + ('signerOnly', 1), + ('fullPath', 2) + ) + + +class CertRefReq(univ.Enumerated): + namedValues = namedval.NamedValues( + ('signerOnly', 1), + ('fullPath', 2) + ) + + +class DeltaTime(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('deltaSeconds', univ.Integer()), + namedtype.NamedType('deltaMinutes', univ.Integer()), + namedtype.NamedType('deltaHours', univ.Integer()), + namedtype.NamedType('deltaDays', univ.Integer()) + ) + + +class TimestampTrustCondition(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('ttsCertificateTrustTrees', + CertificateTrustTrees().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('ttsRevReq', + CertRevReq().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 1))), + namedtype.OptionalNamedType('ttsNameConstraints', + NameConstraints().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 2))), + namedtype.OptionalNamedType('cautionPeriod', + DeltaTime().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 3))), + namedtype.OptionalNamedType('signatureTimestampDelay', + DeltaTime().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 4))) + ) + + +class SignerRules(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('externalSignedData', univ.Boolean()), + namedtype.NamedType('mandatedSignedAttr', CMSAttrs()), + namedtype.NamedType('mandatedUnsignedAttr', CMSAttrs()), + namedtype.DefaultedNamedType('mandatedCertificateRef', + CertRefReq().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0)).subtype( + value='signerOnly')), + namedtype.DefaultedNamedType('mandatedCertificateInfo', + CertInfoReq().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1)).subtype( + value='none')), + namedtype.OptionalNamedType('signPolExtensions', + SignPolExtensions().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 2))) + ) + + +class MandatedUnsignedAttr(CMSAttrs): + pass + + +class VerifierRules(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('mandatedUnsignedAttr', MandatedUnsignedAttr()), + namedtype.OptionalNamedType('signPolExtensions', SignPolExtensions()) + ) + + +class SignerAndVerifierRules(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('signerRules', SignerRules()), + namedtype.NamedType('verifierRules', VerifierRules()) + ) + + +class SigningCertTrustCondition(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('signerTrustTrees', CertificateTrustTrees()), + namedtype.NamedType('signerRevReq', CertRevReq()) + ) + + +class CommitmentTypeIdentifier(univ.ObjectIdentifier): + pass + + +class FieldOfApplication(DirectoryString): + pass + + +class CommitmentType(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('identifier', CommitmentTypeIdentifier()), + namedtype.OptionalNamedType('fieldOfApplication', + FieldOfApplication().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('semantics', + DirectoryString().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))) + ) + + +class SelectedCommitmentTypes(univ.SequenceOf): + componentType = univ.Choice(componentType=namedtype.NamedTypes( + namedtype.NamedType('empty', univ.Null()), + namedtype.NamedType('recognizedCommitmentType', CommitmentType()) + )) + + +class CommitmentRule(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('selCommitmentTypes', SelectedCommitmentTypes()), + namedtype.OptionalNamedType('signerAndVeriferRules', + SignerAndVerifierRules().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.OptionalNamedType('signingCertTrustCondition', + SigningCertTrustCondition().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 1))), + namedtype.OptionalNamedType('timeStampTrustCondition', + TimestampTrustCondition().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 2))), + namedtype.OptionalNamedType('attributeTrustCondition', + AttributeTrustCondition().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 3))), + namedtype.OptionalNamedType('algorithmConstraintSet', + AlgorithmConstraintSet().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 4))), + namedtype.OptionalNamedType('signPolExtensions', + SignPolExtensions().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 5))) + ) + + +class CommitmentRules(univ.SequenceOf): + componentType = CommitmentRule() + + +class CommonRules(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('signerAndVeriferRules', + SignerAndVerifierRules().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.OptionalNamedType('signingCertTrustCondition', + SigningCertTrustCondition().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 1))), + namedtype.OptionalNamedType('timeStampTrustCondition', + TimestampTrustCondition().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 2))), + namedtype.OptionalNamedType('attributeTrustCondition', + AttributeTrustCondition().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 3))), + namedtype.OptionalNamedType('algorithmConstraintSet', + AlgorithmConstraintSet().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 4))), + namedtype.OptionalNamedType('signPolExtensions', + SignPolExtensions().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 5))) + ) + + +class PolicyIssuerName(GeneralNames): + pass + + +class SignPolicyHash(univ.OctetString): + pass + + +class SignPolicyId(univ.ObjectIdentifier): + pass + + +class SigningPeriod(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('notBefore', useful.GeneralizedTime()), + namedtype.OptionalNamedType('notAfter', useful.GeneralizedTime()) + ) + + +class SignatureValidationPolicy(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('signingPeriod', SigningPeriod()), + namedtype.NamedType('commonRules', CommonRules()), + namedtype.NamedType('commitmentRules', CommitmentRules()), + namedtype.OptionalNamedType('signPolExtensions', SignPolExtensions()) + ) + + +class SignPolicyInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('signPolicyIdentifier', SignPolicyId()), + namedtype.NamedType('dateOfIssue', useful.GeneralizedTime()), + namedtype.NamedType('policyIssuerName', PolicyIssuerName()), + namedtype.NamedType('fieldOfApplication', FieldOfApplication()), + namedtype.NamedType('signatureValidationPolicy', SignatureValidationPolicy()), + namedtype.OptionalNamedType('signPolExtensions', SignPolExtensions()) + ) + + +class SignaturePolicy(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('signPolicyHashAlg', AlgorithmIdentifier()), + namedtype.NamedType('signPolicyInfo', SignPolicyInfo()), + namedtype.OptionalNamedType('signPolicyHash', SignPolicyHash()) + ) + + diff --git a/pyasn1_modules/rfc3161.py b/pyasn1_modules/rfc3161.py new file mode 100644 index 0000000..0e1dced --- /dev/null +++ b/pyasn1_modules/rfc3161.py @@ -0,0 +1,142 @@ +# +# 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 +# +# Time-Stamp Protocol (TSP) +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc3161.txt +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import tag +from pyasn1.type import univ +from pyasn1.type import useful + +from pyasn1_modules import rfc4210 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 + + +Extensions = rfc5280.Extensions + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + +GeneralName = rfc5280.GeneralName + +ContentInfo = rfc5652.ContentInfo + +PKIFreeText = rfc4210.PKIFreeText + + +id_ct_TSTInfo = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.4') + + +class Accuracy(univ.Sequence): + pass + +Accuracy.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('seconds', univ.Integer()), + namedtype.OptionalNamedType('millis', univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(1, 999)).subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('micros', univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(1, 999)).subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class MessageImprint(univ.Sequence): + pass + +MessageImprint.componentType = namedtype.NamedTypes( + namedtype.NamedType('hashAlgorithm', AlgorithmIdentifier()), + namedtype.NamedType('hashedMessage', univ.OctetString()) +) + + +class PKIFailureInfo(univ.BitString): + pass + +PKIFailureInfo.namedValues = namedval.NamedValues( + ('badAlg', 0), + ('badRequest', 2), + ('badDataFormat', 5), + ('timeNotAvailable', 14), + ('unacceptedPolicy', 15), + ('unacceptedExtension', 16), + ('addInfoNotAvailable', 17), + ('systemFailure', 25) +) + + +class PKIStatus(univ.Integer): + pass + +PKIStatus.namedValues = namedval.NamedValues( + ('granted', 0), + ('grantedWithMods', 1), + ('rejection', 2), + ('waiting', 3), + ('revocationWarning', 4), + ('revocationNotification', 5) +) + + +class PKIStatusInfo(univ.Sequence): + pass + +PKIStatusInfo.componentType = namedtype.NamedTypes( + namedtype.NamedType('status', PKIStatus()), + namedtype.OptionalNamedType('statusString', PKIFreeText()), + namedtype.OptionalNamedType('failInfo', PKIFailureInfo()) +) + + +class TSAPolicyId(univ.ObjectIdentifier): + pass + + +class TSTInfo(univ.Sequence): + pass + +TSTInfo.componentType = namedtype.NamedTypes( + namedtype.NamedType('version', univ.Integer(namedValues=namedval.NamedValues(('v1', 1)))), + namedtype.NamedType('policy', TSAPolicyId()), + namedtype.NamedType('messageImprint', MessageImprint()), + namedtype.NamedType('serialNumber', univ.Integer()), + namedtype.NamedType('genTime', useful.GeneralizedTime()), + namedtype.OptionalNamedType('accuracy', Accuracy()), + namedtype.DefaultedNamedType('ordering', univ.Boolean().subtype(value=0)), + namedtype.OptionalNamedType('nonce', univ.Integer()), + namedtype.OptionalNamedType('tsa', GeneralName().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('extensions', Extensions().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class TimeStampReq(univ.Sequence): + pass + +TimeStampReq.componentType = namedtype.NamedTypes( + namedtype.NamedType('version', univ.Integer(namedValues=namedval.NamedValues(('v1', 1)))), + namedtype.NamedType('messageImprint', MessageImprint()), + namedtype.OptionalNamedType('reqPolicy', TSAPolicyId()), + namedtype.OptionalNamedType('nonce', univ.Integer()), + namedtype.DefaultedNamedType('certReq', univ.Boolean().subtype(value=0)), + namedtype.OptionalNamedType('extensions', Extensions().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) +) + + +class TimeStampToken(ContentInfo): + pass + + +class TimeStampResp(univ.Sequence): + pass + +TimeStampResp.componentType = namedtype.NamedTypes( + namedtype.NamedType('status', PKIStatusInfo()), + namedtype.OptionalNamedType('timeStampToken', TimeStampToken()) +) diff --git a/pyasn1_modules/rfc3274.py b/pyasn1_modules/rfc3274.py new file mode 100644 index 0000000..425e006 --- /dev/null +++ b/pyasn1_modules/rfc3274.py @@ -0,0 +1,59 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with assistance from asn1ate v.0.6.0. +# Modified by Russ Housley to add a map for use with opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# CMS Compressed Data Content Type +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc3274.txt +# + +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 + + +class CompressionAlgorithmIdentifier(rfc5280.AlgorithmIdentifier): + pass + + +# The CMS Compressed Data Content Type + +id_ct_compressedData = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.9') + +class CompressedData(univ.Sequence): + pass + +CompressedData.componentType = namedtype.NamedTypes( + namedtype.NamedType('version', rfc5652.CMSVersion()), # Always set to 0 + namedtype.NamedType('compressionAlgorithm', CompressionAlgorithmIdentifier()), + namedtype.NamedType('encapContentInfo', rfc5652.EncapsulatedContentInfo()) +) + + +# Algorithm identifier for the zLib Compression Algorithm +# This includes cpa_zlibCompress as defined in RFC 6268, +# from https://www.rfc-editor.org/rfc/rfc6268.txt + +id_alg_zlibCompress = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.8') + +cpa_zlibCompress = rfc5280.AlgorithmIdentifier() +cpa_zlibCompress['algorithm'] = id_alg_zlibCompress +# cpa_zlibCompress['parameters'] are absent + + +# Map of Content Type OIDs to Content Types is added to thr +# ones that are in rfc5652.py + +_cmsContentTypesMapUpdate = { + id_ct_compressedData: CompressedData(), +} + +rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate) diff --git a/pyasn1_modules/rfc3279.py b/pyasn1_modules/rfc3279.py index 65a554d..f6e24de 100644 --- a/pyasn1_modules/rfc3279.py +++ b/pyasn1_modules/rfc3279.py @@ -2,14 +2,21 @@ # This file is part of pyasn1-modules. # # Copyright (c) 2017, Danielle Madeley -# License: http://pyasn1.sf.net/license.html +# License: http://snmplabs.com/pyasn1/license.html # -# Derived from RFC 3279 +# Modified by Russ Housley to add maps for use with opentypes. +# +# Algorithms and Identifiers for Internet X.509 Certificates and CRLs +# +# Derived from RFC 3279: +# https://www.rfc-editor.org/rfc/rfc3279.txt # from pyasn1.type import namedtype from pyasn1.type import namedval from pyasn1.type import univ +from pyasn1_modules import rfc5280 + def _OID(*components): output = [] @@ -231,3 +238,23 @@ class EcpkParameters(univ.Choice): prime239v2 = _OID(primeCurve, 5) prime239v3 = _OID(primeCurve, 6) prime256v1 = _OID(primeCurve, 7) + + +# Map of Algorithm Identifier OIDs to Parameters added to the +# ones in rfc5280.py. Do not add OIDs with absent paramaters. + +_algorithmIdentifierMapUpdate = { + md2: univ.Null(""), + md5: univ.Null(""), + id_sha1: univ.Null(""), + id_dsa: Dss_Parms(), + rsaEncryption: univ.Null(""), + md2WithRSAEncryption: univ.Null(""), + md5WithRSAEncryption: univ.Null(""), + sha1WithRSAEncryption: univ.Null(""), + dhpublicnumber: DomainParameters(), + id_keyExchangeAlgorithm: KEA_Parms_Id(), + id_ecPublicKey: EcpkParameters(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc3280.py b/pyasn1_modules/rfc3280.py index f49dcfb..4c6df13 100644 --- a/pyasn1_modules/rfc3280.py +++ b/pyasn1_modules/rfc3280.py @@ -3,8 +3,8 @@ # This file is part of pyasn1-modules software. # # Created by Stanisław Pitucha with asn1ate tool. -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Internet X.509 Public Key Infrastructure Certificate and Certificate # Revocation List (CRL) Profile @@ -53,7 +53,7 @@ class OrganizationalUnitNames(univ.SequenceOf): OrganizationalUnitNames.componentType = OrganizationalUnitName() -OrganizationalUnitNames.subtypeSpec = constraint.ValueSizeConstraint(1, ub_organizational_units) +OrganizationalUnitNames.sizeSpec = constraint.ValueSizeConstraint(1, ub_organizational_units) class AttributeType(univ.ObjectIdentifier): @@ -152,7 +152,7 @@ class Extensions(univ.SequenceOf): Extensions.componentType = Extension() -Extensions.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +Extensions.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class CertificateSerialNumber(univ.Integer): @@ -219,7 +219,7 @@ class RelativeDistinguishedName(univ.SetOf): RelativeDistinguishedName.componentType = AttributeTypeAndValue() -RelativeDistinguishedName.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +RelativeDistinguishedName.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class RDNSequence(univ.SequenceOf): @@ -519,7 +519,7 @@ class BuiltInDomainDefinedAttributes(univ.SequenceOf): BuiltInDomainDefinedAttributes.componentType = BuiltInDomainDefinedAttribute() -BuiltInDomainDefinedAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, ub_domain_defined_attributes) +BuiltInDomainDefinedAttributes.sizeSpec = constraint.ValueSizeConstraint(1, ub_domain_defined_attributes) ub_extension_attributes = univ.Integer(256) @@ -542,7 +542,7 @@ class ExtensionAttributes(univ.SetOf): ExtensionAttributes.componentType = ExtensionAttribute() -ExtensionAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, ub_extension_attributes) +ExtensionAttributes.sizeSpec = constraint.ValueSizeConstraint(1, ub_extension_attributes) class ORAddress(univ.Sequence): @@ -706,7 +706,7 @@ class TeletexDomainDefinedAttributes(univ.SequenceOf): TeletexDomainDefinedAttributes.componentType = TeletexDomainDefinedAttribute() -TeletexDomainDefinedAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, ub_domain_defined_attributes) +TeletexDomainDefinedAttributes.sizeSpec = constraint.ValueSizeConstraint(1, ub_domain_defined_attributes) class TBSCertList(univ.Sequence): @@ -905,7 +905,7 @@ class TeletexOrganizationalUnitNames(univ.SequenceOf): TeletexOrganizationalUnitNames.componentType = TeletexOrganizationalUnitName() -TeletexOrganizationalUnitNames.subtypeSpec = constraint.ValueSizeConstraint(1, ub_organizational_units) +TeletexOrganizationalUnitNames.sizeSpec = constraint.ValueSizeConstraint(1, ub_organizational_units) physical_delivery_office_name = univ.Integer(10) @@ -1077,7 +1077,7 @@ class GeneralNames(univ.SequenceOf): GeneralNames.componentType = GeneralName() -GeneralNames.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +GeneralNames.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class IssuerAltName(GeneralNames): @@ -1100,7 +1100,7 @@ class PolicyMappings(univ.SequenceOf): namedtype.NamedType('subjectDomainPolicy', CertPolicyId()) )) -PolicyMappings.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +PolicyMappings.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class PolicyQualifierId(univ.ObjectIdentifier): @@ -1119,7 +1119,7 @@ class SubjectDirectoryAttributes(univ.SequenceOf): SubjectDirectoryAttributes.componentType = Attribute() -SubjectDirectoryAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +SubjectDirectoryAttributes.sizeSpec = constraint.ValueSizeConstraint(1, MAX) anyPolicy = _OID(id_ce_certificatePolicies, 0) @@ -1198,7 +1198,7 @@ class CertificatePolicies(univ.SequenceOf): CertificatePolicies.componentType = PolicyInformation() -CertificatePolicies.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +CertificatePolicies.sizeSpec = constraint.ValueSizeConstraint(1, MAX) id_ce_basicConstraints = _OID(id_ce, 19) @@ -1216,7 +1216,7 @@ class ExtKeyUsageSyntax(univ.SequenceOf): ExtKeyUsageSyntax.componentType = KeyPurposeId() -ExtKeyUsageSyntax.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +ExtKeyUsageSyntax.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class SubjectAltName(GeneralNames): @@ -1287,7 +1287,7 @@ class CRLDistributionPoints(univ.SequenceOf): CRLDistributionPoints.componentType = DistributionPoint() -CRLDistributionPoints.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +CRLDistributionPoints.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class FreshestCRL(CRLDistributionPoints): @@ -1340,7 +1340,7 @@ class GeneralSubtrees(univ.SequenceOf): GeneralSubtrees.componentType = GeneralSubtree() -GeneralSubtrees.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +GeneralSubtrees.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class NameConstraints(univ.Sequence): @@ -1389,7 +1389,7 @@ class AuthorityInfoAccessSyntax(univ.SequenceOf): AuthorityInfoAccessSyntax.componentType = AccessDescription() -AuthorityInfoAccessSyntax.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +AuthorityInfoAccessSyntax.sizeSpec = constraint.ValueSizeConstraint(1, MAX) id_ce_issuingDistributionPoint = _OID(id_ce, 28) @@ -1458,7 +1458,7 @@ class SubjectInfoAccessSyntax(univ.SequenceOf): SubjectInfoAccessSyntax.componentType = AccessDescription() -SubjectInfoAccessSyntax.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +SubjectInfoAccessSyntax.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class KeyUsage(univ.BitString): diff --git a/pyasn1_modules/rfc3281.py b/pyasn1_modules/rfc3281.py index 9ecc2cd..a78abf9 100644 --- a/pyasn1_modules/rfc3281.py +++ b/pyasn1_modules/rfc3281.py @@ -3,8 +3,8 @@ # This file is part of pyasn1-modules software. # # Created by Stanisław Pitucha with asn1ate tool. -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # An Internet Attribute Certificate Profile for Authorization # diff --git a/pyasn1_modules/rfc3370.py b/pyasn1_modules/rfc3370.py new file mode 100644 index 0000000..51a9d5c --- /dev/null +++ b/pyasn1_modules/rfc3370.py @@ -0,0 +1,146 @@ +# +# 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 +# +# Cryptographic Message Syntax (CMS) Algorithms +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc3370.txt +# + +from pyasn1.type import univ + +from pyasn1_modules import rfc3279 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5751 +from pyasn1_modules import rfc5753 +from pyasn1_modules import rfc5990 +from pyasn1_modules import rfc8018 + + +# Imports from RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + + +# Imports from RFC 3279 + +dhpublicnumber = rfc3279.dhpublicnumber + +dh_public_number = dhpublicnumber + +DHPublicKey = rfc3279.DHPublicKey + +DomainParameters = rfc3279.DomainParameters + +DHDomainParameters = DomainParameters + +Dss_Parms = rfc3279.Dss_Parms + +Dss_Sig_Value = rfc3279.Dss_Sig_Value + +md5 = rfc3279.md5 + +md5WithRSAEncryption = rfc3279.md5WithRSAEncryption + +RSAPublicKey = rfc3279.RSAPublicKey + +rsaEncryption = rfc3279.rsaEncryption + +ValidationParms = rfc3279.ValidationParms + +id_dsa = rfc3279.id_dsa + +id_dsa_with_sha1 = rfc3279.id_dsa_with_sha1 + +id_sha1 = rfc3279.id_sha1 + +sha_1 = id_sha1 + +sha1WithRSAEncryption = rfc3279.sha1WithRSAEncryption + + +# Imports from RFC 5753 + +CBCParameter = rfc5753.CBCParameter + +CBCParameter = rfc5753.IV + +KeyWrapAlgorithm = rfc5753.KeyWrapAlgorithm + + +# Imports from RFC 5990 + +id_alg_CMS3DESwrap = rfc5990.id_alg_CMS3DESwrap + + +# Imports from RFC 8018 + +des_EDE3_CBC = rfc8018.des_EDE3_CBC + +des_ede3_cbc = des_EDE3_CBC + +rc2CBC = rfc8018.rc2CBC + +rc2_cbc = rc2CBC + +RC2_CBC_Parameter = rfc8018.RC2_CBC_Parameter + +RC2CBCParameter = RC2_CBC_Parameter + +PBKDF2_params = rfc8018.PBKDF2_params + +id_PBKDF2 = rfc8018.id_PBKDF2 + + +# The few things that are not already defined elsewhere + +hMAC_SHA1 = univ.ObjectIdentifier('1.3.6.1.5.5.8.1.2') + + +id_alg_ESDH = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.5') + + +id_alg_SSDH = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.10') + + +id_alg_CMSRC2wrap = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.7') + + +class RC2ParameterVersion(univ.Integer): + pass + + +class RC2wrapParameter(RC2ParameterVersion): + pass + + +class Dss_Pub_Key(univ.Integer): + pass + + +# Update the Algorithm Identifier map in rfc5280.py. + +_algorithmIdentifierMapUpdate = { + hMAC_SHA1: univ.Null(""), + id_alg_CMSRC2wrap: RC2wrapParameter(), + id_alg_ESDH: KeyWrapAlgorithm(), + id_alg_SSDH: KeyWrapAlgorithm(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) + + +# Update the S/MIME Capabilities map in rfc5751.py. + +_smimeCapabilityMapUpdate = { + id_alg_CMSRC2wrap: RC2wrapParameter(), + id_alg_ESDH: KeyWrapAlgorithm(), + id_alg_SSDH: KeyWrapAlgorithm(), +} + +rfc5751.smimeCapabilityMap.update(_smimeCapabilityMapUpdate) diff --git a/pyasn1_modules/rfc3412.py b/pyasn1_modules/rfc3412.py index 1492e62..2cf1e10 100644 --- a/pyasn1_modules/rfc3412.py +++ b/pyasn1_modules/rfc3412.py @@ -1,8 +1,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # SNMPv3 message syntax # diff --git a/pyasn1_modules/rfc3414.py b/pyasn1_modules/rfc3414.py index cac18cf..00420cb 100644 --- a/pyasn1_modules/rfc3414.py +++ b/pyasn1_modules/rfc3414.py @@ -1,8 +1,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # SNMPv3 message syntax # diff --git a/pyasn1_modules/rfc3447.py b/pyasn1_modules/rfc3447.py index a2950aa..3352b70 100644 --- a/pyasn1_modules/rfc3447.py +++ b/pyasn1_modules/rfc3447.py @@ -1,8 +1,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # PKCS#1 syntax # @@ -27,7 +27,7 @@ class OtherPrimeInfo(univ.Sequence): class OtherPrimeInfos(univ.SequenceOf): componentType = OtherPrimeInfo() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX) class RSAPrivateKey(univ.Sequence): diff --git a/pyasn1_modules/rfc3537.py b/pyasn1_modules/rfc3537.py new file mode 100644 index 0000000..374dd81 --- /dev/null +++ b/pyasn1_modules/rfc3537.py @@ -0,0 +1,34 @@ +# +# 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 +# +# SEED Encryption Algorithm in CMS +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc4010.txt +# + +from pyasn1.type import constraint +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +id_alg_HMACwith3DESwrap = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.11') + + +id_alg_HMACwithAESwrap = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.12') + + +# Update the Algorithm Identifier map in rfc5280.py. + +_algorithmIdentifierMapUpdate = { + id_alg_HMACwith3DESwrap: univ.Null(""), + id_alg_HMACwithAESwrap: univ.Null(""), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc3560.py b/pyasn1_modules/rfc3560.py new file mode 100644 index 0000000..8365436 --- /dev/null +++ b/pyasn1_modules/rfc3560.py @@ -0,0 +1,74 @@ +# +# 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 +# +# RSAES-OAEP Key Transport Algorithm in CMS +# +# Notice that all of the things needed in RFC 3560 are also defined +# in RFC 4055. So, they are all pulled from the RFC 4055 module into +# this one so that people looking a RFC 3560 can easily find them. +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc3560.txt +# + +from pyasn1_modules import rfc4055 + +id_sha1 = rfc4055.id_sha1 + +id_sha256 = rfc4055.id_sha256 + +id_sha384 = rfc4055.id_sha384 + +id_sha512 = rfc4055.id_sha512 + +id_mgf1 = rfc4055.id_mgf1 + +rsaEncryption = rfc4055.rsaEncryption + +id_RSAES_OAEP = rfc4055.id_RSAES_OAEP + +id_pSpecified = rfc4055.id_pSpecified + +sha1Identifier = rfc4055.sha1Identifier + +sha256Identifier = rfc4055.sha256Identifier + +sha384Identifier = rfc4055.sha384Identifier + +sha512Identifier = rfc4055.sha512Identifier + +mgf1SHA1Identifier = rfc4055.mgf1SHA1Identifier + +mgf1SHA256Identifier = rfc4055.mgf1SHA256Identifier + +mgf1SHA384Identifier = rfc4055.mgf1SHA384Identifier + +mgf1SHA512Identifier = rfc4055.mgf1SHA512Identifier + +pSpecifiedEmptyIdentifier = rfc4055.pSpecifiedEmptyIdentifier + + +class RSAES_OAEP_params(rfc4055.RSAES_OAEP_params): + pass + + +rSAES_OAEP_Default_Params = RSAES_OAEP_params() + +rSAES_OAEP_Default_Identifier = rfc4055.rSAES_OAEP_Default_Identifier + +rSAES_OAEP_SHA256_Params = rfc4055.rSAES_OAEP_SHA256_Params + +rSAES_OAEP_SHA256_Identifier = rfc4055.rSAES_OAEP_SHA256_Identifier + +rSAES_OAEP_SHA384_Params = rfc4055.rSAES_OAEP_SHA384_Params + +rSAES_OAEP_SHA384_Identifier = rfc4055.rSAES_OAEP_SHA384_Identifier + +rSAES_OAEP_SHA512_Params = rfc4055.rSAES_OAEP_SHA512_Params + +rSAES_OAEP_SHA512_Identifier = rfc4055.rSAES_OAEP_SHA512_Identifier diff --git a/pyasn1_modules/rfc3565.py b/pyasn1_modules/rfc3565.py new file mode 100644 index 0000000..ec75e23 --- /dev/null +++ b/pyasn1_modules/rfc3565.py @@ -0,0 +1,57 @@ +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley. +# Modified by Russ Housley to add maps for use with opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Use of the Advanced Encryption Standard (AES) Encryption +# Algorithm in the Cryptographic Message Syntax (CMS) +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc3565.txt + + +from pyasn1.type import constraint +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +class AlgorithmIdentifier(rfc5280.AlgorithmIdentifier): + pass + + +class AES_IV(univ.OctetString): + pass + +AES_IV.subtypeSpec = constraint.ValueSizeConstraint(16, 16) + + +id_aes128_CBC = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.2') + +id_aes192_CBC = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.22') + +id_aes256_CBC = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.42') + + +id_aes128_wrap = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.5') + +id_aes192_wrap = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.25') + +id_aes256_wrap = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.45') + + +# Update the Algorithm Identifier map + +_algorithmIdentifierMapUpdate = { + id_aes128_CBC: AES_IV(), + id_aes192_CBC: AES_IV(), + id_aes256_CBC: AES_IV(), + id_aes128_wrap: univ.Null(), + id_aes192_wrap: univ.Null(), + id_aes256_wrap: univ.Null(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc3657.py b/pyasn1_modules/rfc3657.py new file mode 100644 index 0000000..ebf23da --- /dev/null +++ b/pyasn1_modules/rfc3657.py @@ -0,0 +1,66 @@ +# +# 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 +# +# Camellia Algorithm in CMS +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc3657.txt +# + +from pyasn1.type import constraint +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5751 + + +id_camellia128_cbc = univ.ObjectIdentifier('1.2.392.200011.61.1.1.1.2') + +id_camellia192_cbc = univ.ObjectIdentifier('1.2.392.200011.61.1.1.1.3') + +id_camellia256_cbc = univ.ObjectIdentifier('1.2.392.200011.61.1.1.1.4') + +id_camellia128_wrap = univ.ObjectIdentifier('1.2.392.200011.61.1.1.3.2') + +id_camellia192_wrap = univ.ObjectIdentifier('1.2.392.200011.61.1.1.3.3') + +id_camellia256_wrap = univ.ObjectIdentifier('1.2.392.200011.61.1.1.3.4') + + + +class Camellia_IV(univ.OctetString): + subtypeSpec = constraint.ValueSizeConstraint(16, 16) + + +class CamelliaSMimeCapability(univ.Null): + pass + + +# Update the Algorithm Identifier map in rfc5280.py. + +_algorithmIdentifierMapUpdate = { + id_camellia128_cbc: Camellia_IV(), + id_camellia192_cbc: Camellia_IV(), + id_camellia256_cbc: Camellia_IV(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) + + +# Update the SMIMECapabilities Attribute map in rfc5751.py + +_smimeCapabilityMapUpdate = { + id_camellia128_cbc: CamelliaSMimeCapability(), + id_camellia192_cbc: CamelliaSMimeCapability(), + id_camellia256_cbc: CamelliaSMimeCapability(), + id_camellia128_wrap: CamelliaSMimeCapability(), + id_camellia192_wrap: CamelliaSMimeCapability(), + id_camellia256_wrap: CamelliaSMimeCapability(), +} + +rfc5751.smimeCapabilityMap.update(_smimeCapabilityMapUpdate) diff --git a/pyasn1_modules/rfc3709.py b/pyasn1_modules/rfc3709.py new file mode 100644 index 0000000..aa1d5b6 --- /dev/null +++ b/pyasn1_modules/rfc3709.py @@ -0,0 +1,207 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with assistance from asn1ate v.0.6.0. +# Modified by Russ Housley to add maps for use with opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Logotypes in X.509 Certificates +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc3709.txt +# + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc6170 + +MAX = float('inf') + + +class HashAlgAndValue(univ.Sequence): + pass + +HashAlgAndValue.componentType = namedtype.NamedTypes( + namedtype.NamedType('hashAlg', rfc5280.AlgorithmIdentifier()), + namedtype.NamedType('hashValue', univ.OctetString()) +) + + +class LogotypeDetails(univ.Sequence): + pass + +LogotypeDetails.componentType = namedtype.NamedTypes( + namedtype.NamedType('mediaType', char.IA5String()), + namedtype.NamedType('logotypeHash', univ.SequenceOf( + componentType=HashAlgAndValue()).subtype( + sizeSpec=constraint.ValueSizeConstraint(1, MAX))), + namedtype.NamedType('logotypeURI', univ.SequenceOf( + componentType=char.IA5String()).subtype( + sizeSpec=constraint.ValueSizeConstraint(1, MAX))) +) + + +class LogotypeAudioInfo(univ.Sequence): + pass + +LogotypeAudioInfo.componentType = namedtype.NamedTypes( + namedtype.NamedType('fileSize', univ.Integer()), + namedtype.NamedType('playTime', univ.Integer()), + namedtype.NamedType('channels', univ.Integer()), + namedtype.OptionalNamedType('sampleRate', univ.Integer().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.OptionalNamedType('language', char.IA5String().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))) +) + + +class LogotypeAudio(univ.Sequence): + pass + +LogotypeAudio.componentType = namedtype.NamedTypes( + namedtype.NamedType('audioDetails', LogotypeDetails()), + namedtype.OptionalNamedType('audioInfo', LogotypeAudioInfo()) +) + + +class LogotypeImageType(univ.Integer): + pass + +LogotypeImageType.namedValues = namedval.NamedValues( + ('grayScale', 0), + ('color', 1) +) + + +class LogotypeImageResolution(univ.Choice): + pass + +LogotypeImageResolution.componentType = namedtype.NamedTypes( + namedtype.NamedType('numBits', + univ.Integer().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('tableSize', + univ.Integer().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 2))) +) + + +class LogotypeImageInfo(univ.Sequence): + pass + +LogotypeImageInfo.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('type', LogotypeImageType().subtype( + implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0)).subtype(value='color')), + namedtype.NamedType('fileSize', univ.Integer()), + namedtype.NamedType('xSize', univ.Integer()), + namedtype.NamedType('ySize', univ.Integer()), + namedtype.OptionalNamedType('resolution', LogotypeImageResolution()), + namedtype.OptionalNamedType('language', char.IA5String().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))) +) + + +class LogotypeImage(univ.Sequence): + pass + +LogotypeImage.componentType = namedtype.NamedTypes( + namedtype.NamedType('imageDetails', LogotypeDetails()), + namedtype.OptionalNamedType('imageInfo', LogotypeImageInfo()) +) + + +class LogotypeData(univ.Sequence): + pass + +LogotypeData.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('image', univ.SequenceOf( + componentType=LogotypeImage())), + namedtype.OptionalNamedType('audio', univ.SequenceOf( + componentType=LogotypeAudio()).subtype( + implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 1))) +) + + +class LogotypeReference(univ.Sequence): + pass + +LogotypeReference.componentType = namedtype.NamedTypes( + namedtype.NamedType('refStructHash', univ.SequenceOf( + componentType=HashAlgAndValue()).subtype( + sizeSpec=constraint.ValueSizeConstraint(1, MAX))), + namedtype.NamedType('refStructURI', univ.SequenceOf( + componentType=char.IA5String()).subtype( + sizeSpec=constraint.ValueSizeConstraint(1, MAX))) +) + + +class LogotypeInfo(univ.Choice): + pass + +LogotypeInfo.componentType = namedtype.NamedTypes( + namedtype.NamedType('direct', + LogotypeData().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatConstructed, 0))), + namedtype.NamedType('indirect', LogotypeReference().subtype( + implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatConstructed, 1))) +) + +# Other logotype type and associated object identifiers + +id_logo_background = univ.ObjectIdentifier('1.3.6.1.5.5.7.20.2') + +id_logo_loyalty = univ.ObjectIdentifier('1.3.6.1.5.5.7.20.1') + +id_logo_certImage = rfc6170.id_logo_certImage + + +class OtherLogotypeInfo(univ.Sequence): + pass + +OtherLogotypeInfo.componentType = namedtype.NamedTypes( + namedtype.NamedType('logotypeType', univ.ObjectIdentifier()), + namedtype.NamedType('info', LogotypeInfo()) +) + + +# Logotype Certificate Extension + +id_pe_logotype = univ.ObjectIdentifier('1.3.6.1.5.5.7.1.12') + + +class LogotypeExtn(univ.Sequence): + pass + +LogotypeExtn.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('communityLogos', univ.SequenceOf( + componentType=LogotypeInfo()).subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('issuerLogo', LogotypeInfo().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))), + namedtype.OptionalNamedType('subjectLogo', LogotypeInfo().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))), + namedtype.OptionalNamedType('otherLogos', univ.SequenceOf( + componentType=OtherLogotypeInfo()).subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 3))) +) + + +# Map of Certificate Extension OIDs to Extensions added to the +# ones that are in rfc5280.py + +_certificateExtensionsMapUpdate = { + id_pe_logotype: LogotypeExtn(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMapUpdate) diff --git a/pyasn1_modules/rfc3739.py b/pyasn1_modules/rfc3739.py new file mode 100644 index 0000000..4aa5aaf --- /dev/null +++ b/pyasn1_modules/rfc3739.py @@ -0,0 +1,203 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with assistance from asn1ate v.0.6.0. +# Modified by Russ Housley to add WithComponentsConstraints to +# enforce the requirements that are indicated in comments. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Qualified Certificates +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc3739.txt +# + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import opentype +from pyasn1.type import univ +from pyasn1.type import useful + +from pyasn1_modules import rfc5280 + +MAX = float('inf') + + +# Initialize the qcStatement map + +qcStatementMap = { } + + +# Imports from RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + +AttributeType = rfc5280.AttributeType + +DirectoryString = rfc5280.DirectoryString + +GeneralName = rfc5280.GeneralName + +id_pkix = rfc5280.id_pkix + +id_pe = rfc5280.id_pe + + +# Arc for QC personal data attributes + +id_pda = id_pkix + (9, ) + + +# Arc for QC statements + +id_qcs = id_pkix + (11, ) + + +# Personal data attributes + +id_pda_dateOfBirth = id_pda + (1, ) + +class DateOfBirth(useful.GeneralizedTime): + pass + + +id_pda_placeOfBirth = id_pda + (2, ) + +class PlaceOfBirth(DirectoryString): + pass + + +id_pda_gender = id_pda + (3, ) + +class Gender(char.PrintableString): + subtypeSpec = constraint.ConstraintsIntersection( + constraint.ValueSizeConstraint(1, 1), + constraint.SingleValueConstraint('M', 'F', 'm', 'f') + ) + + +id_pda_countryOfCitizenship = id_pda + (4, ) + +class CountryOfCitizenship(char.PrintableString): + subtypeSpec = constraint.ValueSizeConstraint(2, 2) + # ISO 3166 Country Code + + +id_pda_countryOfResidence = id_pda + (5, ) + +class CountryOfResidence(char.PrintableString): + subtypeSpec = constraint.ValueSizeConstraint(2, 2) + # ISO 3166 Country Code + + +# Biometric info certificate extension + +id_pe_biometricInfo = id_pe + (2, ) + + +class PredefinedBiometricType(univ.Integer): + namedValues = namedval.NamedValues( + ('picture', 0), + ('handwritten-signature', 1) + ) + subtypeSpec = constraint.SingleValueConstraint(0, 1) + + +class TypeOfBiometricData(univ.Choice): + componentType = namedtype.NamedTypes( + namedtype.NamedType('predefinedBiometricType', PredefinedBiometricType()), + namedtype.NamedType('biometricDataOid', univ.ObjectIdentifier()) + ) + + +class BiometricData(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('typeOfBiometricData', TypeOfBiometricData()), + namedtype.NamedType('hashAlgorithm', AlgorithmIdentifier()), + namedtype.NamedType('biometricDataHash', univ.OctetString()), + namedtype.OptionalNamedType('sourceDataUri', char.IA5String()) + ) + + +class BiometricSyntax(univ.SequenceOf): + componentType = BiometricData() + + +# QC Statements certificate extension +# NOTE: This extension does not allow to mix critical and +# non-critical Qualified Certificate Statements. Either all +# statements must be critical or all statements must be +# non-critical. + +id_pe_qcStatements = id_pe + (3, ) + + +class NameRegistrationAuthorities(univ.SequenceOf): + componentType = GeneralName() + subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + + +class QCStatement(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('statementId', univ.ObjectIdentifier()), + namedtype.OptionalNamedType('statementInfo', univ.Any(), + openType=opentype.OpenType('statementId', qcStatementMap)) + ) + + +class QCStatements(univ.SequenceOf): + componentType = QCStatement() + + +class SemanticsInformation(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('semanticsIndentifier', + univ.ObjectIdentifier()), + namedtype.OptionalNamedType('nameRegistrationAuthorities', + NameRegistrationAuthorities()) + ) + subtypeSpec = constraint.ConstraintsUnion( + constraint.WithComponentsConstraint( + ('semanticsIndentifier', constraint.ComponentPresentConstraint())), + constraint.WithComponentsConstraint( + ('nameRegistrationAuthorities', constraint.ComponentPresentConstraint())) + ) + + +id_qcs = id_pkix + (11, ) + + +id_qcs_pkixQCSyntax_v1 = id_qcs + (1, ) + + +id_qcs_pkixQCSyntax_v2 = id_qcs + (2, ) + + +# Map of Certificate Extension OIDs to Extensions +# To be added to the ones that are in rfc5280.py + +_certificateExtensionsMap = { + id_pe_biometricInfo: BiometricSyntax(), + id_pe_qcStatements: QCStatements(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMap) + + +# Map of AttributeType OIDs to AttributeValue added to the +# ones that are in rfc5280.py + +_certificateAttributesMapUpdate = { + id_pda_dateOfBirth: DateOfBirth(), + id_pda_placeOfBirth: PlaceOfBirth(), + id_pda_gender: Gender(), + id_pda_countryOfCitizenship: CountryOfCitizenship(), + id_pda_countryOfResidence: CountryOfResidence(), +} + +rfc5280.certificateAttributesMap.update(_certificateAttributesMapUpdate) + diff --git a/pyasn1_modules/rfc3770.py b/pyasn1_modules/rfc3770.py new file mode 100644 index 0000000..3fefe1d --- /dev/null +++ b/pyasn1_modules/rfc3770.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/rfc3770.txt +# https://www.rfc-editor.org/errata/eid234 +# + +from pyasn1.type import constraint +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +MAX = float('inf') + + +# Extended Key Usage Values + +id_kp_eapOverLAN = univ.ObjectIdentifier('1.3.6.1.5.5.7.3.14') + +id_kp_eapOverPPP = univ.ObjectIdentifier('1.3.6.1.5.5.7.3.13') + + +# Wireless LAN SSID Extension + +id_pe_wlanSSID = univ.ObjectIdentifier('1.3.6.1.5.5.7.1.13') + + +class SSID(univ.OctetString): + pass + +SSID.subtypeSpec = constraint.ValueSizeConstraint(1, 32) + + +class SSIDList(univ.SequenceOf): + pass + +SSIDList.componentType = SSID() +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.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/pyasn1_modules/rfc3779.py b/pyasn1_modules/rfc3779.py new file mode 100644 index 0000000..8e6eaa3 --- /dev/null +++ b/pyasn1_modules/rfc3779.py @@ -0,0 +1,137 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with assistance from asn1ate v.0.6.0. +# Modified by Russ Housley to add maps for use with opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# X.509 Extensions for IP Addresses and AS Identifiers +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc3779.txt +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +# IP Address Delegation Extension + +id_pe_ipAddrBlocks = univ.ObjectIdentifier('1.3.6.1.5.5.7.1.7') + + +class IPAddress(univ.BitString): + pass + + +class IPAddressRange(univ.Sequence): + pass + +IPAddressRange.componentType = namedtype.NamedTypes( + namedtype.NamedType('min', IPAddress()), + namedtype.NamedType('max', IPAddress()) +) + + +class IPAddressOrRange(univ.Choice): + pass + +IPAddressOrRange.componentType = namedtype.NamedTypes( + namedtype.NamedType('addressPrefix', IPAddress()), + namedtype.NamedType('addressRange', IPAddressRange()) +) + + +class IPAddressChoice(univ.Choice): + pass + +IPAddressChoice.componentType = namedtype.NamedTypes( + namedtype.NamedType('inherit', univ.Null()), + namedtype.NamedType('addressesOrRanges', univ.SequenceOf( + componentType=IPAddressOrRange()) + ) +) + + +class IPAddressFamily(univ.Sequence): + pass + +IPAddressFamily.componentType = namedtype.NamedTypes( + namedtype.NamedType('addressFamily', univ.OctetString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(2, 3))), + namedtype.NamedType('ipAddressChoice', IPAddressChoice()) +) + + +class IPAddrBlocks(univ.SequenceOf): + pass + +IPAddrBlocks.componentType = IPAddressFamily() + + +# Autonomous System Identifier Delegation Extension + +id_pe_autonomousSysIds = univ.ObjectIdentifier('1.3.6.1.5.5.7.1.8') + + +class ASId(univ.Integer): + pass + + +class ASRange(univ.Sequence): + pass + +ASRange.componentType = namedtype.NamedTypes( + namedtype.NamedType('min', ASId()), + namedtype.NamedType('max', ASId()) +) + + +class ASIdOrRange(univ.Choice): + pass + +ASIdOrRange.componentType = namedtype.NamedTypes( + namedtype.NamedType('id', ASId()), + namedtype.NamedType('range', ASRange()) +) + + +class ASIdentifierChoice(univ.Choice): + pass + +ASIdentifierChoice.componentType = namedtype.NamedTypes( + namedtype.NamedType('inherit', univ.Null()), + namedtype.NamedType('asIdsOrRanges', univ.SequenceOf( + componentType=ASIdOrRange()) + ) +) + + +class ASIdentifiers(univ.Sequence): + pass + +ASIdentifiers.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('asnum', ASIdentifierChoice().subtype( + explicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatConstructed, 0))), + namedtype.OptionalNamedType('rdi', ASIdentifierChoice().subtype( + explicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatConstructed, 1))) +) + + +# Map of Certificate Extension OIDs to Extensions is added to the +# ones that are in rfc5280.py + +_certificateExtensionsMapUpdate = { + id_pe_ipAddrBlocks: IPAddrBlocks(), + id_pe_autonomousSysIds: ASIdentifiers(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMapUpdate) diff --git a/pyasn1_modules/rfc3820.py b/pyasn1_modules/rfc3820.py new file mode 100644 index 0000000..b4ba34c --- /dev/null +++ b/pyasn1_modules/rfc3820.py @@ -0,0 +1,65 @@ +# +# 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 +# +# Diffie-Hellman Key Agreement +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc3820.txt +# + +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + + +class ProxyCertPathLengthConstraint(univ.Integer): + pass + + +class ProxyPolicy(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('policyLanguage', univ.ObjectIdentifier()), + namedtype.OptionalNamedType('policy', univ.OctetString()) + ) + + +class ProxyCertInfoExtension(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('pCPathLenConstraint', + ProxyCertPathLengthConstraint()), + namedtype.NamedType('proxyPolicy', ProxyPolicy()) + ) + + +id_pkix = univ.ObjectIdentifier((1, 3, 6, 1, 5, 5, 7, )) + + +id_pe = id_pkix + (1, ) + +id_pe_proxyCertInfo = id_pe + (14, ) + + +id_ppl = id_pkix + (21, ) + +id_ppl_anyLanguage = id_ppl + (0, ) + +id_ppl_inheritAll = id_ppl + (1, ) + +id_ppl_independent = id_ppl + (2, ) + + +# Map of Certificate Extension OIDs to Extensions added to the +# ones that are in rfc5280.py + +_certificateExtensionsMapUpdate = { + id_pe_proxyCertInfo: ProxyCertInfoExtension(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMapUpdate) diff --git a/pyasn1_modules/rfc3852.py b/pyasn1_modules/rfc3852.py index 3b17fe5..cf1bb85 100644 --- a/pyasn1_modules/rfc3852.py +++ b/pyasn1_modules/rfc3852.py @@ -3,8 +3,8 @@ # This file is part of pyasn1-modules software. # # Created by Stanisław Pitucha with asn1ate tool. -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Cryptographic Message Syntax (CMS) # @@ -54,7 +54,7 @@ class SignedAttributes(univ.SetOf): SignedAttributes.componentType = Attribute() -SignedAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +SignedAttributes.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class OtherRevocationInfoFormat(univ.Sequence): @@ -309,7 +309,7 @@ class RecipientInfos(univ.SetOf): RecipientInfos.componentType = RecipientInfo() -RecipientInfos.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +RecipientInfos.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class DigestAlgorithmIdentifier(rfc3280.AlgorithmIdentifier): @@ -336,7 +336,7 @@ class UnprotectedAttributes(univ.SetOf): UnprotectedAttributes.componentType = Attribute() -UnprotectedAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +UnprotectedAttributes.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class ContentType(univ.ObjectIdentifier): @@ -430,7 +430,7 @@ class UnauthAttributes(univ.SetOf): UnauthAttributes.componentType = Attribute() -UnauthAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +UnauthAttributes.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class ExtendedCertificateInfo(univ.Sequence): @@ -550,7 +550,7 @@ class UnsignedAttributes(univ.SetOf): UnsignedAttributes.componentType = Attribute() -UnsignedAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +UnsignedAttributes.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class SignatureValue(univ.OctetString): @@ -632,7 +632,7 @@ class AuthAttributes(univ.SetOf): AuthAttributes.componentType = Attribute() -AuthAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +AuthAttributes.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class AuthenticatedData(univ.Sequence): diff --git a/pyasn1_modules/rfc4010.py b/pyasn1_modules/rfc4010.py new file mode 100644 index 0000000..4981f76 --- /dev/null +++ b/pyasn1_modules/rfc4010.py @@ -0,0 +1,58 @@ +# +# 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 +# +# SEED Encryption Algorithm in CMS +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc4010.txt +# + +from pyasn1.type import constraint +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5751 + + +id_seedCBC = univ.ObjectIdentifier('1.2.410.200004.1.4') + + +id_npki_app_cmsSeed_wrap = univ.ObjectIdentifier('1.2.410.200004.7.1.1.1') + + +class SeedIV(univ.OctetString): + subtypeSpec = constraint.ValueSizeConstraint(16, 16) + + +class SeedCBCParameter(SeedIV): + pass + + +class SeedSMimeCapability(univ.Null): + pass + + +# Update the Algorithm Identifier map in rfc5280.py. + +_algorithmIdentifierMapUpdate = { + id_seedCBC: SeedCBCParameter(), + id_npki_app_cmsSeed_wrap: univ.Null(""), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) + + +# Update the SMIMECapabilities Attribute map in rfc5751.py + +_smimeCapabilityMapUpdate = { + id_seedCBC: SeedSMimeCapability(), + id_npki_app_cmsSeed_wrap: SeedSMimeCapability(), + +} + +rfc5751.smimeCapabilityMap.update(_smimeCapabilityMapUpdate) diff --git a/pyasn1_modules/rfc4043.py b/pyasn1_modules/rfc4043.py new file mode 100644 index 0000000..cf0a801 --- /dev/null +++ b/pyasn1_modules/rfc4043.py @@ -0,0 +1,43 @@ +# +# 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 +# +# Internet X.509 Public Key Infrastructure Permanent Identifier +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc4043.txt +# + +from pyasn1.type import char +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +id_pkix = univ.ObjectIdentifier((1, 3, 6, 1, 5, 5, 7, )) + +id_on = id_pkix + (8, ) + +id_on_permanentIdentifier = id_on + (3, ) + + +class PermanentIdentifier(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('identifierValue', char.UTF8String()), + namedtype.OptionalNamedType('assigner', univ.ObjectIdentifier()) + ) + + +# Map of Other Name OIDs to Other Name is added to the +# ones that are in rfc5280.py + +_anotherNameMapUpdate = { + id_on_permanentIdentifier: PermanentIdentifier(), +} + +rfc5280.anotherNameMap.update(_anotherNameMapUpdate) diff --git a/pyasn1_modules/rfc4055.py b/pyasn1_modules/rfc4055.py new file mode 100644 index 0000000..bdc1286 --- /dev/null +++ b/pyasn1_modules/rfc4055.py @@ -0,0 +1,258 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with a very small amount of assistance from +# asn1ate v.0.6.0. +# Modified by Russ Housley to add maps for opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Additional Algorithms and Identifiers for RSA Cryptography +# for use in Certificates and CRLs +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc4055.txt +# +from pyasn1.type import namedtype +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +def _OID(*components): + output = [] + for x in tuple(components): + if isinstance(x, univ.ObjectIdentifier): + output.extend(list(x)) + else: + output.append(int(x)) + return univ.ObjectIdentifier(output) + + +id_sha1 = _OID(1, 3, 14, 3, 2, 26) + +id_sha256 = _OID(2, 16, 840, 1, 101, 3, 4, 2, 1) + +id_sha384 = _OID(2, 16, 840, 1, 101, 3, 4, 2, 2) + +id_sha512 = _OID(2, 16, 840, 1, 101, 3, 4, 2, 3) + +id_sha224 = _OID(2, 16, 840, 1, 101, 3, 4, 2, 4) + +rsaEncryption = _OID(1, 2, 840, 113549, 1, 1, 1) + +id_mgf1 = _OID(1, 2, 840, 113549, 1, 1, 8) + +id_RSAES_OAEP = _OID(1, 2, 840, 113549, 1, 1, 7) + +id_pSpecified = _OID(1, 2, 840, 113549, 1, 1, 9) + +id_RSASSA_PSS = _OID(1, 2, 840, 113549, 1, 1, 10) + +sha256WithRSAEncryption = _OID(1, 2, 840, 113549, 1, 1, 11) + +sha384WithRSAEncryption = _OID(1, 2, 840, 113549, 1, 1, 12) + +sha512WithRSAEncryption = _OID(1, 2, 840, 113549, 1, 1, 13) + +sha224WithRSAEncryption = _OID(1, 2, 840, 113549, 1, 1, 14) + +sha1Identifier = rfc5280.AlgorithmIdentifier() +sha1Identifier['algorithm'] = id_sha1 +sha1Identifier['parameters'] = univ.Null("") + +sha224Identifier = rfc5280.AlgorithmIdentifier() +sha224Identifier['algorithm'] = id_sha224 +sha224Identifier['parameters'] = univ.Null("") + +sha256Identifier = rfc5280.AlgorithmIdentifier() +sha256Identifier['algorithm'] = id_sha256 +sha256Identifier['parameters'] = univ.Null("") + +sha384Identifier = rfc5280.AlgorithmIdentifier() +sha384Identifier['algorithm'] = id_sha384 +sha384Identifier['parameters'] = univ.Null("") + +sha512Identifier = rfc5280.AlgorithmIdentifier() +sha512Identifier['algorithm'] = id_sha512 +sha512Identifier['parameters'] = univ.Null("") + +mgf1SHA1Identifier = rfc5280.AlgorithmIdentifier() +mgf1SHA1Identifier['algorithm'] = id_mgf1 +mgf1SHA1Identifier['parameters'] = sha1Identifier + +mgf1SHA224Identifier = rfc5280.AlgorithmIdentifier() +mgf1SHA224Identifier['algorithm'] = id_mgf1 +mgf1SHA224Identifier['parameters'] = sha224Identifier + +mgf1SHA256Identifier = rfc5280.AlgorithmIdentifier() +mgf1SHA256Identifier['algorithm'] = id_mgf1 +mgf1SHA256Identifier['parameters'] = sha256Identifier + +mgf1SHA384Identifier = rfc5280.AlgorithmIdentifier() +mgf1SHA384Identifier['algorithm'] = id_mgf1 +mgf1SHA384Identifier['parameters'] = sha384Identifier + +mgf1SHA512Identifier = rfc5280.AlgorithmIdentifier() +mgf1SHA512Identifier['algorithm'] = id_mgf1 +mgf1SHA512Identifier['parameters'] = sha512Identifier + +pSpecifiedEmptyIdentifier = rfc5280.AlgorithmIdentifier() +pSpecifiedEmptyIdentifier['algorithm'] = id_pSpecified +pSpecifiedEmptyIdentifier['parameters'] = univ.OctetString(value='') + + +class RSAPublicKey(univ.Sequence): + pass + +RSAPublicKey.componentType = namedtype.NamedTypes( + namedtype.NamedType('modulus', univ.Integer()), + namedtype.NamedType('publicExponent', univ.Integer()) +) + + +class HashAlgorithm(rfc5280.AlgorithmIdentifier): + pass + + +class MaskGenAlgorithm(rfc5280.AlgorithmIdentifier): + pass + + +class RSAES_OAEP_params(univ.Sequence): + pass + +RSAES_OAEP_params.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('hashFunc', rfc5280.AlgorithmIdentifier().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.OptionalNamedType('maskGenFunc', rfc5280.AlgorithmIdentifier().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))), + namedtype.OptionalNamedType('pSourceFunc', rfc5280.AlgorithmIdentifier().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))) +) + +rSAES_OAEP_Default_Params = RSAES_OAEP_params() + +rSAES_OAEP_Default_Identifier = rfc5280.AlgorithmIdentifier() +rSAES_OAEP_Default_Identifier['algorithm'] = id_RSAES_OAEP +rSAES_OAEP_Default_Identifier['parameters'] = rSAES_OAEP_Default_Params + +rSAES_OAEP_SHA224_Params = RSAES_OAEP_params() +rSAES_OAEP_SHA224_Params['hashFunc'] = sha224Identifier.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0), cloneValueFlag=True) +rSAES_OAEP_SHA224_Params['maskGenFunc'] = mgf1SHA224Identifier.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), cloneValueFlag=True) + +rSAES_OAEP_SHA224_Identifier = rfc5280.AlgorithmIdentifier() +rSAES_OAEP_SHA224_Identifier['algorithm'] = id_RSAES_OAEP +rSAES_OAEP_SHA224_Identifier['parameters'] = rSAES_OAEP_SHA224_Params + +rSAES_OAEP_SHA256_Params = RSAES_OAEP_params() +rSAES_OAEP_SHA256_Params['hashFunc'] = sha256Identifier.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0), cloneValueFlag=True) +rSAES_OAEP_SHA256_Params['maskGenFunc'] = mgf1SHA256Identifier.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), cloneValueFlag=True) + +rSAES_OAEP_SHA256_Identifier = rfc5280.AlgorithmIdentifier() +rSAES_OAEP_SHA256_Identifier['algorithm'] = id_RSAES_OAEP +rSAES_OAEP_SHA256_Identifier['parameters'] = rSAES_OAEP_SHA256_Params + +rSAES_OAEP_SHA384_Params = RSAES_OAEP_params() +rSAES_OAEP_SHA384_Params['hashFunc'] = sha384Identifier.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0), cloneValueFlag=True) +rSAES_OAEP_SHA384_Params['maskGenFunc'] = mgf1SHA384Identifier.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), cloneValueFlag=True) + +rSAES_OAEP_SHA384_Identifier = rfc5280.AlgorithmIdentifier() +rSAES_OAEP_SHA384_Identifier['algorithm'] = id_RSAES_OAEP +rSAES_OAEP_SHA384_Identifier['parameters'] = rSAES_OAEP_SHA384_Params + +rSAES_OAEP_SHA512_Params = RSAES_OAEP_params() +rSAES_OAEP_SHA512_Params['hashFunc'] = sha512Identifier.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0), cloneValueFlag=True) +rSAES_OAEP_SHA512_Params['maskGenFunc'] = mgf1SHA512Identifier.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), cloneValueFlag=True) + +rSAES_OAEP_SHA512_Identifier = rfc5280.AlgorithmIdentifier() +rSAES_OAEP_SHA512_Identifier['algorithm'] = id_RSAES_OAEP +rSAES_OAEP_SHA512_Identifier['parameters'] = rSAES_OAEP_SHA512_Params + + +class RSASSA_PSS_params(univ.Sequence): + pass + +RSASSA_PSS_params.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('hashAlgorithm', rfc5280.AlgorithmIdentifier().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.OptionalNamedType('maskGenAlgorithm', rfc5280.AlgorithmIdentifier().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))), + namedtype.DefaultedNamedType('saltLength', univ.Integer(value=20).subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.DefaultedNamedType('trailerField', univ.Integer(value=1).subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))) +) + +rSASSA_PSS_Default_Params = RSASSA_PSS_params() + +rSASSA_PSS_Default_Identifier = rfc5280.AlgorithmIdentifier() +rSASSA_PSS_Default_Identifier['algorithm'] = id_RSASSA_PSS +rSASSA_PSS_Default_Identifier['parameters'] = rSASSA_PSS_Default_Params + +rSASSA_PSS_SHA224_Params = RSASSA_PSS_params() +rSASSA_PSS_SHA224_Params['hashAlgorithm'] = sha224Identifier.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0), cloneValueFlag=True) +rSASSA_PSS_SHA224_Params['maskGenAlgorithm'] = mgf1SHA224Identifier.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), cloneValueFlag=True) + +rSASSA_PSS_SHA224_Identifier = rfc5280.AlgorithmIdentifier() +rSASSA_PSS_SHA224_Identifier['algorithm'] = id_RSASSA_PSS +rSASSA_PSS_SHA224_Identifier['parameters'] = rSASSA_PSS_SHA224_Params + +rSASSA_PSS_SHA256_Params = RSASSA_PSS_params() +rSASSA_PSS_SHA256_Params['hashAlgorithm'] = sha256Identifier.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0), cloneValueFlag=True) +rSASSA_PSS_SHA256_Params['maskGenAlgorithm'] = mgf1SHA256Identifier.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), cloneValueFlag=True) + +rSASSA_PSS_SHA256_Identifier = rfc5280.AlgorithmIdentifier() +rSASSA_PSS_SHA256_Identifier['algorithm'] = id_RSASSA_PSS +rSASSA_PSS_SHA256_Identifier['parameters'] = rSASSA_PSS_SHA256_Params + +rSASSA_PSS_SHA384_Params = RSASSA_PSS_params() +rSASSA_PSS_SHA384_Params['hashAlgorithm'] = sha384Identifier.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0), cloneValueFlag=True) +rSASSA_PSS_SHA384_Params['maskGenAlgorithm'] = mgf1SHA384Identifier.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), cloneValueFlag=True) + +rSASSA_PSS_SHA384_Identifier = rfc5280.AlgorithmIdentifier() +rSASSA_PSS_SHA384_Identifier['algorithm'] = id_RSASSA_PSS +rSASSA_PSS_SHA384_Identifier['parameters'] = rSASSA_PSS_SHA384_Params + +rSASSA_PSS_SHA512_Params = RSASSA_PSS_params() +rSASSA_PSS_SHA512_Params['hashAlgorithm'] = sha512Identifier.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0), cloneValueFlag=True) +rSASSA_PSS_SHA512_Params['maskGenAlgorithm'] = mgf1SHA512Identifier.subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), cloneValueFlag=True) + +rSASSA_PSS_SHA512_Identifier = rfc5280.AlgorithmIdentifier() +rSASSA_PSS_SHA512_Identifier['algorithm'] = id_RSASSA_PSS +rSASSA_PSS_SHA512_Identifier['parameters'] = rSASSA_PSS_SHA512_Params + + +# Update the Algorithm Identifier map + +_algorithmIdentifierMapUpdate = { + id_sha1: univ.Null(), + id_sha224: univ.Null(), + id_sha256: univ.Null(), + id_sha384: univ.Null(), + id_sha512: univ.Null(), + id_mgf1: rfc5280.AlgorithmIdentifier(), + id_pSpecified: univ.OctetString(), + id_RSAES_OAEP: RSAES_OAEP_params(), + id_RSASSA_PSS: RSASSA_PSS_params(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc4073.py b/pyasn1_modules/rfc4073.py new file mode 100644 index 0000000..3f425b2 --- /dev/null +++ b/pyasn1_modules/rfc4073.py @@ -0,0 +1,59 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with some assistance from asn1ate v.0.6.0. +# Modified by Russ Housley to add a map for use with opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Protecting Multiple Contents with the CMS +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc4073.txt +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5652 + +MAX = float('inf') + + +# Content Collection Content Type and Object Identifier + +id_ct_contentCollection = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.19') + +class ContentCollection(univ.SequenceOf): + pass + +ContentCollection.componentType = rfc5652.ContentInfo() +ContentCollection.sizeSpec = constraint.ValueSizeConstraint(1, MAX) + + +# Content With Attributes Content Type and Object Identifier + +id_ct_contentWithAttrs = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.20') + +class ContentWithAttributes(univ.Sequence): + pass + +ContentWithAttributes.componentType = namedtype.NamedTypes( + namedtype.NamedType('content', rfc5652.ContentInfo()), + namedtype.NamedType('attrs', univ.SequenceOf( + componentType=rfc5652.Attribute()).subtype( + sizeSpec=constraint.ValueSizeConstraint(1, MAX))) +) + + +# Map of Content Type OIDs to Content Types is added to the +# ones that are in rfc5652.py + +_cmsContentTypesMapUpdate = { + id_ct_contentCollection: ContentCollection(), + id_ct_contentWithAttrs: ContentWithAttributes(), +} + +rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate) diff --git a/pyasn1_modules/rfc4108.py b/pyasn1_modules/rfc4108.py new file mode 100644 index 0000000..ecace9e --- /dev/null +++ b/pyasn1_modules/rfc4108.py @@ -0,0 +1,350 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with assistance from asn1ate v.0.6.0. +# Modified by Russ Housley to add items from the verified errata. +# Modified by Russ Housley to add maps for use with opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# CMS Firmware Wrapper +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc4108.txt +# https://www.rfc-editor.org/errata_search.php?rfc=4108 +# + + +from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful + +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 + +MAX = float('inf') + + +class HardwareSerialEntry(univ.Choice): + pass + +HardwareSerialEntry.componentType = namedtype.NamedTypes( + namedtype.NamedType('all', univ.Null()), + namedtype.NamedType('single', univ.OctetString()), + namedtype.NamedType('block', univ.Sequence(componentType=namedtype.NamedTypes( + namedtype.NamedType('low', univ.OctetString()), + namedtype.NamedType('high', univ.OctetString()) + )) + ) +) + + +class HardwareModules(univ.Sequence): + pass + +HardwareModules.componentType = namedtype.NamedTypes( + namedtype.NamedType('hwType', univ.ObjectIdentifier()), + namedtype.NamedType('hwSerialEntries', univ.SequenceOf(componentType=HardwareSerialEntry())) +) + + +class CommunityIdentifier(univ.Choice): + pass + +CommunityIdentifier.componentType = namedtype.NamedTypes( + namedtype.NamedType('communityOID', univ.ObjectIdentifier()), + namedtype.NamedType('hwModuleList', HardwareModules()) +) + + + +class PreferredPackageIdentifier(univ.Sequence): + pass + +PreferredPackageIdentifier.componentType = namedtype.NamedTypes( + namedtype.NamedType('fwPkgID', univ.ObjectIdentifier()), + namedtype.NamedType('verNum', univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, MAX))) +) + + +class PreferredOrLegacyPackageIdentifier(univ.Choice): + pass + +PreferredOrLegacyPackageIdentifier.componentType = namedtype.NamedTypes( + namedtype.NamedType('preferred', PreferredPackageIdentifier()), + namedtype.NamedType('legacy', univ.OctetString()) +) + + +class CurrentFWConfig(univ.Sequence): + pass + +CurrentFWConfig.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('fwPkgType', univ.Integer()), + namedtype.NamedType('fwPkgName', PreferredOrLegacyPackageIdentifier()) +) + + +class PreferredOrLegacyStalePackageIdentifier(univ.Choice): + pass + +PreferredOrLegacyStalePackageIdentifier.componentType = namedtype.NamedTypes( + namedtype.NamedType('preferredStaleVerNum', univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, MAX))), + namedtype.NamedType('legacyStaleVersion', univ.OctetString()) +) + + +class FirmwarePackageLoadErrorCode(univ.Enumerated): + pass + +FirmwarePackageLoadErrorCode.namedValues = namedval.NamedValues( + ('decodeFailure', 1), + ('badContentInfo', 2), + ('badSignedData', 3), + ('badEncapContent', 4), + ('badCertificate', 5), + ('badSignerInfo', 6), + ('badSignedAttrs', 7), + ('badUnsignedAttrs', 8), + ('missingContent', 9), + ('noTrustAnchor', 10), + ('notAuthorized', 11), + ('badDigestAlgorithm', 12), + ('badSignatureAlgorithm', 13), + ('unsupportedKeySize', 14), + ('signatureFailure', 15), + ('contentTypeMismatch', 16), + ('badEncryptedData', 17), + ('unprotectedAttrsPresent', 18), + ('badEncryptContent', 19), + ('badEncryptAlgorithm', 20), + ('missingCiphertext', 21), + ('noDecryptKey', 22), + ('decryptFailure', 23), + ('badCompressAlgorithm', 24), + ('missingCompressedContent', 25), + ('decompressFailure', 26), + ('wrongHardware', 27), + ('stalePackage', 28), + ('notInCommunity', 29), + ('unsupportedPackageType', 30), + ('missingDependency', 31), + ('wrongDependencyVersion', 32), + ('insufficientMemory', 33), + ('badFirmware', 34), + ('unsupportedParameters', 35), + ('breaksDependency', 36), + ('otherError', 99) +) + + +class VendorLoadErrorCode(univ.Integer): + pass + + +# Wrapped Firmware Key Unsigned Attribute and Object Identifier + +id_aa_wrappedFirmwareKey = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.39') + +class WrappedFirmwareKey(rfc5652.EnvelopedData): + pass + + +# Firmware Package Information Signed Attribute and Object Identifier + +id_aa_firmwarePackageInfo = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.42') + +class FirmwarePackageInfo(univ.Sequence): + pass + +FirmwarePackageInfo.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('fwPkgType', univ.Integer()), + namedtype.OptionalNamedType('dependencies', univ.SequenceOf(componentType=PreferredOrLegacyPackageIdentifier())) +) + +FirmwarePackageInfo.sizeSpec = univ.Sequence.sizeSpec + constraint.ValueSizeConstraint(1, 2) + + +# Community Identifiers Signed Attribute and Object Identifier + +id_aa_communityIdentifiers = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.40') + +class CommunityIdentifiers(univ.SequenceOf): + pass + +CommunityIdentifiers.componentType = CommunityIdentifier() + + +# Implemented Compression Algorithms Signed Attribute and Object Identifier + +id_aa_implCompressAlgs = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.43') + +class ImplementedCompressAlgorithms(univ.SequenceOf): + pass + +ImplementedCompressAlgorithms.componentType = univ.ObjectIdentifier() + + +# Implemented Cryptographic Algorithms Signed Attribute and Object Identifier + +id_aa_implCryptoAlgs = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.38') + +class ImplementedCryptoAlgorithms(univ.SequenceOf): + pass + +ImplementedCryptoAlgorithms.componentType = univ.ObjectIdentifier() + + +# Decrypt Key Identifier Signed Attribute and Object Identifier + +id_aa_decryptKeyID = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.37') + +class DecryptKeyIdentifier(univ.OctetString): + pass + + +# Target Hardware Identifier Signed Attribute and Object Identifier + +id_aa_targetHardwareIDs = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.36') + +class TargetHardwareIdentifiers(univ.SequenceOf): + pass + +TargetHardwareIdentifiers.componentType = univ.ObjectIdentifier() + + +# Firmware Package Identifier Signed Attribute and Object Identifier + +id_aa_firmwarePackageID = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.35') + +class FirmwarePackageIdentifier(univ.Sequence): + pass + +FirmwarePackageIdentifier.componentType = namedtype.NamedTypes( + namedtype.NamedType('name', PreferredOrLegacyPackageIdentifier()), + namedtype.OptionalNamedType('stale', PreferredOrLegacyStalePackageIdentifier()) +) + + +# Firmware Package Message Digest Signed Attribute and Object Identifier + +id_aa_fwPkgMessageDigest = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.41') + +class FirmwarePackageMessageDigest(univ.Sequence): + pass + +FirmwarePackageMessageDigest.componentType = namedtype.NamedTypes( + namedtype.NamedType('algorithm', rfc5280.AlgorithmIdentifier()), + namedtype.NamedType('msgDigest', univ.OctetString()) +) + + +# Firmware Package Load Error Report Content Type and Object Identifier + +class FWErrorVersion(univ.Integer): + pass + +FWErrorVersion.namedValues = namedval.NamedValues( + ('v1', 1) +) + + +id_ct_firmwareLoadError = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.18') + +class FirmwarePackageLoadError(univ.Sequence): + pass + +FirmwarePackageLoadError.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', FWErrorVersion().subtype(value='v1')), + namedtype.NamedType('hwType', univ.ObjectIdentifier()), + namedtype.NamedType('hwSerialNum', univ.OctetString()), + namedtype.NamedType('errorCode', FirmwarePackageLoadErrorCode()), + namedtype.OptionalNamedType('vendorErrorCode', VendorLoadErrorCode()), + namedtype.OptionalNamedType('fwPkgName', PreferredOrLegacyPackageIdentifier()), + namedtype.OptionalNamedType('config', univ.SequenceOf(componentType=CurrentFWConfig()).subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +# Firmware Package Load Receipt Content Type and Object Identifier + +class FWReceiptVersion(univ.Integer): + pass + +FWReceiptVersion.namedValues = namedval.NamedValues( + ('v1', 1) +) + + +id_ct_firmwareLoadReceipt = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.17') + +class FirmwarePackageLoadReceipt(univ.Sequence): + pass + +FirmwarePackageLoadReceipt.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', FWReceiptVersion().subtype(value='v1')), + namedtype.NamedType('hwType', univ.ObjectIdentifier()), + namedtype.NamedType('hwSerialNum', univ.OctetString()), + namedtype.NamedType('fwPkgName', PreferredOrLegacyPackageIdentifier()), + namedtype.OptionalNamedType('trustAnchorKeyID', univ.OctetString()), + namedtype.OptionalNamedType('decryptKeyID', univ.OctetString().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +# Firmware Package Content Type and Object Identifier + +id_ct_firmwarePackage = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.16') + +class FirmwarePkgData(univ.OctetString): + pass + + +# Other Name syntax for Hardware Module Name + +id_on_hardwareModuleName = univ.ObjectIdentifier('1.3.6.1.5.5.7.8.4') + +class HardwareModuleName(univ.Sequence): + pass + +HardwareModuleName.componentType = namedtype.NamedTypes( + namedtype.NamedType('hwType', univ.ObjectIdentifier()), + namedtype.NamedType('hwSerialNum', univ.OctetString()) +) + + +# Map of Attribute Type OIDs to Attributes is added to the +# ones that are in rfc5652.py + +_cmsAttributesMapUpdate = { + id_aa_wrappedFirmwareKey: WrappedFirmwareKey(), + id_aa_firmwarePackageInfo: FirmwarePackageInfo(), + id_aa_communityIdentifiers: CommunityIdentifiers(), + id_aa_implCompressAlgs: ImplementedCompressAlgorithms(), + id_aa_implCryptoAlgs: ImplementedCryptoAlgorithms(), + id_aa_decryptKeyID: DecryptKeyIdentifier(), + id_aa_targetHardwareIDs: TargetHardwareIdentifiers(), + id_aa_firmwarePackageID: FirmwarePackageIdentifier(), + id_aa_fwPkgMessageDigest: FirmwarePackageMessageDigest(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) + + +# Map of Content Type OIDs to Content Types is added to the +# ones that are in rfc5652.py + +_cmsContentTypesMapUpdate = { + id_ct_firmwareLoadError: FirmwarePackageLoadError(), + id_ct_firmwareLoadReceipt: FirmwarePackageLoadReceipt(), + id_ct_firmwarePackage: FirmwarePkgData(), +} + +rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate) + + +# Map of Other Name OIDs to Other Name is added to the +# ones that are in rfc5280.py + +_anotherNameMapUpdate = { + id_on_hardwareModuleName: HardwareModuleName(), +} + +rfc5280.anotherNameMap.update(_anotherNameMapUpdate) diff --git a/pyasn1_modules/rfc4210.py b/pyasn1_modules/rfc4210.py index b93464f..0935e3e 100644 --- a/pyasn1_modules/rfc4210.py +++ b/pyasn1_modules/rfc4210.py @@ -1,8 +1,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Certificate Management Protocol structures as per RFC4210 # @@ -44,7 +44,7 @@ class PKIFreeText(univ.SequenceOf): PKIFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String """ componentType = char.UTF8String() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX) class PollRepContent(univ.SequenceOf): @@ -354,16 +354,21 @@ class RevRepContent(univ.Sequence): OPTIONAL """ componentType = namedtype.NamedTypes( - namedtype.NamedType('status', PKIStatusInfo()), + namedtype.NamedType( + 'status', univ.SequenceOf( + componentType=PKIStatusInfo(), + sizeSpec=constraint.ValueSizeConstraint(1, MAX) + ) + ), namedtype.OptionalNamedType( 'revCerts', univ.SequenceOf(componentType=rfc2511.CertId()).subtype( - subtypeSpec=constraint.ValueSizeConstraint(1, MAX), + sizeSpec=constraint.ValueSizeConstraint(1, MAX), explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0) ) ), namedtype.OptionalNamedType( 'crls', univ.SequenceOf(componentType=rfc2459.CertificateList()).subtype( - subtypeSpec=constraint.ValueSizeConstraint(1, MAX), + sizeSpec=constraint.ValueSizeConstraint(1, MAX), explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1) ) ) @@ -391,12 +396,12 @@ class KeyRecRepContent(univ.Sequence): namedtype.OptionalNamedType( 'caCerts', univ.SequenceOf(componentType=CMPCertificate()).subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), - subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + sizeSpec=constraint.ValueSizeConstraint(1, MAX) ) ), namedtype.OptionalNamedType('keyPairHist', univ.SequenceOf(componentType=CertifiedKeyPair()).subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2), - subtypeSpec=constraint.ValueSizeConstraint(1, MAX)) + sizeSpec=constraint.ValueSizeConstraint(1, MAX)) ) ) @@ -430,7 +435,8 @@ class CertRepMessage(univ.Sequence): namedtype.OptionalNamedType( 'caPubs', univ.SequenceOf( componentType=CMPCertificate() - ).subtype(subtypeSpec=constraint.ValueSizeConstraint(1, MAX), explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)) + ).subtype(sizeSpec=constraint.ValueSizeConstraint(1, MAX), + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)) ), namedtype.NamedType('response', univ.SequenceOf(componentType=CertResponse())) ) @@ -737,11 +743,11 @@ class PKIHeader(univ.Sequence): namedtype.OptionalNamedType('generalInfo', univ.SequenceOf( componentType=InfoTypeAndValue().subtype( - subtypeSpec=constraint.ValueSizeConstraint(1, MAX), - explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 8) + sizeSpec=constraint.ValueSizeConstraint(1, MAX) ) - ) - ) + ).subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 8)) + ) ) @@ -776,7 +782,7 @@ class PKIMessage(univ.Sequence): univ.SequenceOf( componentType=CMPCertificate() ).subtype( - subtypeSpec=constraint.ValueSizeConstraint(1, MAX), + sizeSpec=constraint.ValueSizeConstraint(1, MAX), explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1) ) ) @@ -788,7 +794,7 @@ class PKIMessages(univ.SequenceOf): PKIMessages ::= SEQUENCE SIZE (1..MAX) OF PKIMessage """ componentType = PKIMessage() - subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX) + sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX) # pyasn1 does not naturally handle recursive definitions, thus this hack: diff --git a/pyasn1_modules/rfc4211.py b/pyasn1_modules/rfc4211.py index 9ff07f2..c47b3c5 100644 --- a/pyasn1_modules/rfc4211.py +++ b/pyasn1_modules/rfc4211.py @@ -3,8 +3,8 @@ # This file is part of pyasn1-modules software. # # Created by Stanisław Pitucha with asn1ate tool. -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Internet X.509 Public Key Infrastructure Certificate Request # Message Format (CRMF) @@ -282,7 +282,7 @@ class Controls(univ.SequenceOf): Controls.componentType = AttributeTypeAndValue() -Controls.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +Controls.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class CertRequest(univ.Sequence): @@ -312,7 +312,7 @@ class CertReqMessages(univ.SequenceOf): CertReqMessages.componentType = CertReqMsg() -CertReqMessages.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +CertReqMessages.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class CertReq(CertRequest): 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/pyasn1_modules/rfc4357.py b/pyasn1_modules/rfc4357.py new file mode 100644 index 0000000..42b9e3e --- /dev/null +++ b/pyasn1_modules/rfc4357.py @@ -0,0 +1,477 @@ +# +# 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 +# +# Additional Cryptographic Algorithms for Use with GOST 28147-89, +# GOST R 34.10-94, GOST R 34.10-2001, and GOST R 34.11-94 Algorithms +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc4357.txt +# https://www.rfc-editor.org/errata/eid5927 +# https://www.rfc-editor.org/errata/eid5928 +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +# Import from RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + + +# Object Identifiers + +id_CryptoPro = univ.ObjectIdentifier((1, 2, 643, 2, 2,)) + + +id_CryptoPro_modules = id_CryptoPro + (1, 1,) + +id_CryptoPro_extensions = id_CryptoPro + (34,) + +id_CryptoPro_policyIds = id_CryptoPro + (38,) + +id_CryptoPro_policyQt = id_CryptoPro + (39,) + + +cryptographic_Gost_Useful_Definitions = id_CryptoPro_modules + (0, 1,) + +gostR3411_94_DigestSyntax = id_CryptoPro_modules + (1, 1,) + +gostR3410_94_PKISyntax = id_CryptoPro_modules + (2, 1,) + +gostR3410_94_SignatureSyntax = id_CryptoPro_modules + (3, 1,) + +gost28147_89_EncryptionSyntax = id_CryptoPro_modules + (4, 1,) + +gostR3410_EncryptionSyntax = id_CryptoPro_modules + (5, 2,) + +gost28147_89_ParamSetSyntax = id_CryptoPro_modules + (6, 1,) + +gostR3411_94_ParamSetSyntax = id_CryptoPro_modules + (7, 1,) + +gostR3410_94_ParamSetSyntax = id_CryptoPro_modules + (8, 1, 1) + +gostR3410_2001_PKISyntax = id_CryptoPro_modules + (9, 1,) + +gostR3410_2001_SignatureSyntax = id_CryptoPro_modules + (10, 1,) + +gostR3410_2001_ParamSetSyntax = id_CryptoPro_modules + (12, 1,) + +gost_CryptoPro_ExtendedKeyUsage = id_CryptoPro_modules + (13, 1,) + +gost_CryptoPro_PrivateKey = id_CryptoPro_modules + (14, 1,) + +gost_CryptoPro_PKIXCMP = id_CryptoPro_modules + (15, 1,) + +gost_CryptoPro_TLS = id_CryptoPro_modules + (16, 1,) + +gost_CryptoPro_Policy = id_CryptoPro_modules + (17, 1,) + +gost_CryptoPro_Constants = id_CryptoPro_modules + (18, 1,) + + +id_CryptoPro_algorithms = id_CryptoPro + +id_GostR3411_94_with_GostR3410_2001 = id_CryptoPro_algorithms + (3,) + +id_GostR3411_94_with_GostR3410_94 = id_CryptoPro_algorithms + (4,) + +id_GostR3411_94 = id_CryptoPro_algorithms + (9,) + +id_Gost28147_89_None_KeyMeshing = id_CryptoPro_algorithms + (14, 0,) + +id_Gost28147_89_CryptoPro_KeyMeshing = id_CryptoPro_algorithms + (14, 1,) + +id_GostR3410_2001 = id_CryptoPro_algorithms + (19,) + +id_GostR3410_94 = id_CryptoPro_algorithms + (20,) + +id_Gost28147_89 = id_CryptoPro_algorithms + (21,) + +id_Gost28147_89_MAC = id_CryptoPro_algorithms + (22,) + +id_CryptoPro_hashes = id_CryptoPro_algorithms + (30,) + +id_CryptoPro_encrypts = id_CryptoPro_algorithms + (31,) + +id_CryptoPro_signs = id_CryptoPro_algorithms + (32,) + +id_CryptoPro_exchanges = id_CryptoPro_algorithms + (33,) + +id_CryptoPro_ecc_signs = id_CryptoPro_algorithms + (35,) + +id_CryptoPro_ecc_exchanges = id_CryptoPro_algorithms + (36,) + +id_CryptoPro_private_keys = id_CryptoPro_algorithms + (37,) + +id_CryptoPro_pkixcmp_infos = id_CryptoPro_algorithms + (41,) + +id_CryptoPro_audit_service_types = id_CryptoPro_algorithms + (42,) + +id_CryptoPro_audit_record_types = id_CryptoPro_algorithms + (43,) + +id_CryptoPro_attributes = id_CryptoPro_algorithms + (44,) + +id_CryptoPro_name_service_types = id_CryptoPro_algorithms + (45,) + +id_GostR3410_2001DH = id_CryptoPro_algorithms + (98,) + +id_GostR3410_94DH = id_CryptoPro_algorithms + (99,) + + +id_Gost28147_89_TestParamSet = id_CryptoPro_encrypts + (0,) + +id_Gost28147_89_CryptoPro_A_ParamSet = id_CryptoPro_encrypts + (1,) + +id_Gost28147_89_CryptoPro_B_ParamSet = id_CryptoPro_encrypts + (2,) + +id_Gost28147_89_CryptoPro_C_ParamSet = id_CryptoPro_encrypts + (3,) + +id_Gost28147_89_CryptoPro_D_ParamSet = id_CryptoPro_encrypts + (4,) + +id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet = id_CryptoPro_encrypts + (5,) + +id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet = id_CryptoPro_encrypts + (6,) + +id_Gost28147_89_CryptoPro_RIC_1_ParamSet = id_CryptoPro_encrypts + (7,) + + +id_GostR3410_2001_TestParamSet = id_CryptoPro_ecc_signs + (0,) + +id_GostR3410_2001_CryptoPro_A_ParamSet = id_CryptoPro_ecc_signs + (1,) + +id_GostR3410_2001_CryptoPro_B_ParamSet = id_CryptoPro_ecc_signs + (2,) + +id_GostR3410_2001_CryptoPro_C_ParamSet = id_CryptoPro_ecc_signs + (3,) + + +id_GostR3410_2001_CryptoPro_XchA_ParamSet = id_CryptoPro_ecc_exchanges + (0,) + +id_GostR3410_2001_CryptoPro_XchB_ParamSet = id_CryptoPro_ecc_exchanges + (1,) + + +id_GostR3410_94_TestParamSet = id_CryptoPro_signs + (0,) + +id_GostR3410_94_CryptoPro_A_ParamSet = id_CryptoPro_signs + (2,) + +id_GostR3410_94_CryptoPro_B_ParamSet = id_CryptoPro_signs + (3,) + +id_GostR3410_94_CryptoPro_C_ParamSet = id_CryptoPro_signs + (4,) + +id_GostR3410_94_CryptoPro_D_ParamSet = id_CryptoPro_signs + (5,) + + +id_GostR3410_94_CryptoPro_XchA_ParamSet = id_CryptoPro_exchanges + (1,) + +id_GostR3410_94_CryptoPro_XchB_ParamSet = id_CryptoPro_exchanges + (2,) + +id_GostR3410_94_CryptoPro_XchC_ParamSet = id_CryptoPro_exchanges + (3,) + + +id_GostR3410_94_a = id_GostR3410_94 + (1,) + +id_GostR3410_94_aBis = id_GostR3410_94 + (2,) + +id_GostR3410_94_b = id_GostR3410_94 + (3,) + +id_GostR3410_94_bBis = id_GostR3410_94 + (4,) + + +id_GostR3411_94_TestParamSet = id_CryptoPro_hashes + (0,) + +id_GostR3411_94_CryptoProParamSet = id_CryptoPro_hashes + (1,) + + + + +class Gost28147_89_ParamSet(univ.ObjectIdentifier): + pass + +Gost28147_89_ParamSet.subtypeSpec = constraint.SingleValueConstraint( + id_Gost28147_89_TestParamSet, + id_Gost28147_89_CryptoPro_A_ParamSet, + id_Gost28147_89_CryptoPro_B_ParamSet, + id_Gost28147_89_CryptoPro_C_ParamSet, + id_Gost28147_89_CryptoPro_D_ParamSet, + id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet, + id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet, + id_Gost28147_89_CryptoPro_RIC_1_ParamSet +) + + +class Gost28147_89_BlobParameters(univ.Sequence): + pass + +Gost28147_89_BlobParameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('encryptionParamSet', Gost28147_89_ParamSet()) +) + + +class Gost28147_89_MAC(univ.OctetString): + pass + +Gost28147_89_MAC.subtypeSpec = constraint.ValueSizeConstraint(1, 4) + + +class Gost28147_89_Key(univ.OctetString): + pass + +Gost28147_89_Key.subtypeSpec = constraint.ValueSizeConstraint(32, 32) + + +class Gost28147_89_EncryptedKey(univ.Sequence): + pass + +Gost28147_89_EncryptedKey.componentType = namedtype.NamedTypes( + namedtype.NamedType('encryptedKey', Gost28147_89_Key()), + namedtype.OptionalNamedType('maskKey', Gost28147_89_Key().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('macKey', Gost28147_89_MAC()) +) + + +class Gost28147_89_IV(univ.OctetString): + pass + +Gost28147_89_IV.subtypeSpec = constraint.ValueSizeConstraint(8, 8) + + +class Gost28147_89_UZ(univ.OctetString): + pass + +Gost28147_89_UZ.subtypeSpec = constraint.ValueSizeConstraint(64, 64) + + +class Gost28147_89_ParamSetParameters(univ.Sequence): + pass + +Gost28147_89_ParamSetParameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('eUZ', Gost28147_89_UZ()), + namedtype.NamedType('mode', + univ.Integer(namedValues=namedval.NamedValues( + ('gost28147-89-CNT', 0), + ('gost28147-89-CFB', 1), + ('cryptoPro-CBC', 2) + ))), + namedtype.NamedType('shiftBits', + univ.Integer(namedValues=namedval.NamedValues( + ('gost28147-89-block', 64) + ))), + namedtype.NamedType('keyMeshing', AlgorithmIdentifier()) +) + + +class Gost28147_89_Parameters(univ.Sequence): + pass + +Gost28147_89_Parameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('iv', Gost28147_89_IV()), + namedtype.NamedType('encryptionParamSet', Gost28147_89_ParamSet()) +) + + +class GostR3410_2001_CertificateSignature(univ.BitString): + pass + +GostR3410_2001_CertificateSignature.subtypeSpec=constraint.ValueSizeConstraint(256, 512) + + +class GostR3410_2001_ParamSetParameters(univ.Sequence): + pass + +GostR3410_2001_ParamSetParameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('a', univ.Integer()), + namedtype.NamedType('b', univ.Integer()), + namedtype.NamedType('p', univ.Integer()), + namedtype.NamedType('q', univ.Integer()), + namedtype.NamedType('x', univ.Integer()), + namedtype.NamedType('y', univ.Integer()) +) + + +class GostR3410_2001_PublicKey(univ.OctetString): + pass + +GostR3410_2001_PublicKey.subtypeSpec = constraint.ValueSizeConstraint(64, 64) + + +class GostR3410_2001_PublicKeyParameters(univ.Sequence): + pass + +GostR3410_2001_PublicKeyParameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('publicKeyParamSet', univ.ObjectIdentifier().subtype( + subtypeSpec=constraint.SingleValueConstraint( + id_GostR3410_2001_TestParamSet, + id_GostR3410_2001_CryptoPro_A_ParamSet, + id_GostR3410_2001_CryptoPro_B_ParamSet, + id_GostR3410_2001_CryptoPro_C_ParamSet, + id_GostR3410_2001_CryptoPro_XchA_ParamSet, + id_GostR3410_2001_CryptoPro_XchB_ParamSet + ))), + namedtype.NamedType('digestParamSet', univ.ObjectIdentifier().subtype( + subtypeSpec=constraint.SingleValueConstraint( + id_GostR3411_94_TestParamSet, + id_GostR3411_94_CryptoProParamSet + ))), + namedtype.DefaultedNamedType('encryptionParamSet', + Gost28147_89_ParamSet().subtype(value=id_Gost28147_89_CryptoPro_A_ParamSet + )) +) + + +class GostR3410_94_CertificateSignature(univ.BitString): + pass + +GostR3410_94_CertificateSignature.subtypeSpec = constraint.ValueSizeConstraint(256, 512) + + +class GostR3410_94_ParamSetParameters_t(univ.Integer): + pass + +GostR3410_94_ParamSetParameters_t.subtypeSpec = constraint.SingleValueConstraint(512, 1024) + + +class GostR3410_94_ParamSetParameters(univ.Sequence): + pass + +GostR3410_94_ParamSetParameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('t', GostR3410_94_ParamSetParameters_t()), + namedtype.NamedType('p', univ.Integer()), + namedtype.NamedType('q', univ.Integer()), + namedtype.NamedType('a', univ.Integer()), + namedtype.OptionalNamedType('validationAlgorithm', AlgorithmIdentifier()) +) + + +class GostR3410_94_PublicKey(univ.OctetString): + pass + +GostR3410_94_PublicKey.subtypeSpec = constraint.ConstraintsUnion( + constraint.ValueSizeConstraint(64, 64), + constraint.ValueSizeConstraint(128, 128) +) + + +class GostR3410_94_PublicKeyParameters(univ.Sequence): + pass + +GostR3410_94_PublicKeyParameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('publicKeyParamSet', univ.ObjectIdentifier().subtype( + subtypeSpec=constraint.SingleValueConstraint( + id_GostR3410_94_TestParamSet, + id_GostR3410_94_CryptoPro_A_ParamSet, + id_GostR3410_94_CryptoPro_B_ParamSet, + id_GostR3410_94_CryptoPro_C_ParamSet, + id_GostR3410_94_CryptoPro_D_ParamSet, + id_GostR3410_94_CryptoPro_XchA_ParamSet, + id_GostR3410_94_CryptoPro_XchB_ParamSet, + id_GostR3410_94_CryptoPro_XchC_ParamSet + ))), + namedtype.NamedType('digestParamSet', univ.ObjectIdentifier().subtype( + subtypeSpec=constraint.SingleValueConstraint( + id_GostR3411_94_TestParamSet, + id_GostR3411_94_CryptoProParamSet + ))), + namedtype.DefaultedNamedType('encryptionParamSet', + Gost28147_89_ParamSet().subtype(value=id_Gost28147_89_CryptoPro_A_ParamSet + )) +) + + +class GostR3410_94_ValidationBisParameters_c(univ.Integer): + pass + +GostR3410_94_ValidationBisParameters_c.subtypeSpec = constraint.ValueRangeConstraint(0, 4294967295) + + +class GostR3410_94_ValidationBisParameters(univ.Sequence): + pass + +GostR3410_94_ValidationBisParameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('x0', GostR3410_94_ValidationBisParameters_c()), + namedtype.NamedType('c', GostR3410_94_ValidationBisParameters_c()), + namedtype.OptionalNamedType('d', univ.Integer()) +) + + +class GostR3410_94_ValidationParameters_c(univ.Integer): + pass + +GostR3410_94_ValidationParameters_c.subtypeSpec = constraint.ValueRangeConstraint(0, 65535) + + +class GostR3410_94_ValidationParameters(univ.Sequence): + pass + +GostR3410_94_ValidationParameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('x0', GostR3410_94_ValidationParameters_c()), + namedtype.NamedType('c', GostR3410_94_ValidationParameters_c()), + namedtype.OptionalNamedType('d', univ.Integer()) +) + + +class GostR3411_94_Digest(univ.OctetString): + pass + +GostR3411_94_Digest.subtypeSpec = constraint.ValueSizeConstraint(32, 32) + + +class GostR3411_94_DigestParameters(univ.ObjectIdentifier): + pass + +GostR3411_94_DigestParameters.subtypeSpec = constraint.ConstraintsUnion( + constraint.SingleValueConstraint(id_GostR3411_94_TestParamSet), + constraint.SingleValueConstraint(id_GostR3411_94_CryptoProParamSet), +) + + +class GostR3411_94_ParamSetParameters(univ.Sequence): + pass + +GostR3411_94_ParamSetParameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('hUZ', Gost28147_89_UZ()), + namedtype.NamedType('h0', GostR3411_94_Digest()) +) + + +# Update the Algorithm Identifier map in rfc5280.py + +_algorithmIdentifierMapUpdate = { + id_Gost28147_89: Gost28147_89_Parameters(), + id_Gost28147_89_TestParamSet: Gost28147_89_ParamSetParameters(), + id_Gost28147_89_CryptoPro_A_ParamSet: Gost28147_89_ParamSetParameters(), + id_Gost28147_89_CryptoPro_B_ParamSet: Gost28147_89_ParamSetParameters(), + id_Gost28147_89_CryptoPro_C_ParamSet: Gost28147_89_ParamSetParameters(), + id_Gost28147_89_CryptoPro_D_ParamSet: Gost28147_89_ParamSetParameters(), + id_Gost28147_89_CryptoPro_KeyMeshing: univ.Null(""), + id_Gost28147_89_None_KeyMeshing: univ.Null(""), + id_GostR3410_94: GostR3410_94_PublicKeyParameters(), + id_GostR3410_94_TestParamSet: GostR3410_94_ParamSetParameters(), + id_GostR3410_94_CryptoPro_A_ParamSet: GostR3410_94_ParamSetParameters(), + id_GostR3410_94_CryptoPro_B_ParamSet: GostR3410_94_ParamSetParameters(), + id_GostR3410_94_CryptoPro_C_ParamSet: GostR3410_94_ParamSetParameters(), + id_GostR3410_94_CryptoPro_D_ParamSet: GostR3410_94_ParamSetParameters(), + id_GostR3410_94_CryptoPro_XchA_ParamSet: GostR3410_94_ParamSetParameters(), + id_GostR3410_94_CryptoPro_XchB_ParamSet: GostR3410_94_ParamSetParameters(), + id_GostR3410_94_CryptoPro_XchC_ParamSet: GostR3410_94_ParamSetParameters(), + id_GostR3410_94_a: GostR3410_94_ValidationParameters(), + id_GostR3410_94_aBis: GostR3410_94_ValidationBisParameters(), + id_GostR3410_94_b: GostR3410_94_ValidationParameters(), + id_GostR3410_94_bBis: GostR3410_94_ValidationBisParameters(), + id_GostR3410_2001: univ.Null(""), + id_GostR3411_94: univ.Null(""), + id_GostR3411_94_TestParamSet: GostR3411_94_ParamSetParameters(), + id_GostR3411_94_CryptoProParamSet: GostR3411_94_ParamSetParameters(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc4387.py b/pyasn1_modules/rfc4387.py new file mode 100644 index 0000000..c1f4e79 --- /dev/null +++ b/pyasn1_modules/rfc4387.py @@ -0,0 +1,23 @@ +# +# 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 +# +# Certificate Store Access via HTTP +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc4387.txt +# + + +from pyasn1.type import univ + + +id_ad = univ.ObjectIdentifier((1, 3, 6, 1, 5, 5, 7, 48, )) + +id_ad_http_certs = id_ad + (6, ) + +id_ad_http_crls = id_ad + (7,) diff --git a/pyasn1_modules/rfc4476.py b/pyasn1_modules/rfc4476.py new file mode 100644 index 0000000..25a0ccb --- /dev/null +++ b/pyasn1_modules/rfc4476.py @@ -0,0 +1,93 @@ +# +# 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 +# +# Attribute Certificate Policies Extension +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc4476.txt +# + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + +MAX = float('inf') + + +# Imports from RFC 5280 + +PolicyQualifierId = rfc5280.PolicyQualifierId + +PolicyQualifierInfo = rfc5280.PolicyQualifierInfo + +UserNotice = rfc5280.UserNotice + +id_pkix = rfc5280.id_pkix + + +# Object Identifiers + +id_pe = id_pkix + (1,) + +id_pe_acPolicies = id_pe + (15,) + +id_qt = id_pkix + (2,) + +id_qt_acps = id_qt + (4,) + +id_qt_acunotice = id_qt + (5,) + + +# Attribute Certificate Policies Extension + +class ACUserNotice(UserNotice): + pass + + +class ACPSuri(char.IA5String): + pass + + +class AcPolicyId(univ.ObjectIdentifier): + pass + + +class PolicyInformation(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('policyIdentifier', AcPolicyId()), + namedtype.OptionalNamedType('policyQualifiers', + univ.SequenceOf(componentType=PolicyQualifierInfo()).subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, MAX))) + ) + + +class AcPoliciesSyntax(univ.SequenceOf): + componentType = PolicyInformation() + subtypeSpec = constraint.ValueSizeConstraint(1, MAX) + + +# Update the policy qualifier map in rfc5280.py + +_policyQualifierInfoMapUpdate = { + id_qt_acps: ACPSuri(), + id_qt_acunotice: UserNotice(), +} + +rfc5280.policyQualifierInfoMap.update(_policyQualifierInfoMapUpdate) + + +# Update the certificate extension map in rfc5280.py + +_certificateExtensionsMapUpdate = { + id_pe_acPolicies: AcPoliciesSyntax(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMapUpdate) diff --git a/pyasn1_modules/rfc4490.py b/pyasn1_modules/rfc4490.py new file mode 100644 index 0000000..b8fe321 --- /dev/null +++ b/pyasn1_modules/rfc4490.py @@ -0,0 +1,113 @@ +# +# 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 +# +# Using the GOST 28147-89, GOST R 34.11-94, GOST R 34.10-94, and +# GOST R 34.10-2001 Algorithms with the CMS +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc4490.txt +# + + +from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful + +from pyasn1_modules import rfc4357 +from pyasn1_modules import rfc5280 + + +# Imports from RFC 4357 + +id_CryptoPro_algorithms = rfc4357.id_CryptoPro_algorithms + +id_GostR3410_94 = rfc4357.id_GostR3410_94 + +id_GostR3410_2001 = rfc4357.id_GostR3410_2001 + +Gost28147_89_ParamSet = rfc4357.Gost28147_89_ParamSet + +Gost28147_89_EncryptedKey = rfc4357.Gost28147_89_EncryptedKey + +GostR3410_94_PublicKeyParameters = rfc4357.GostR3410_94_PublicKeyParameters + +GostR3410_2001_PublicKeyParameters = rfc4357.GostR3410_2001_PublicKeyParameters + + +# Imports from RFC 5280 + +SubjectPublicKeyInfo = rfc5280.SubjectPublicKeyInfo + + +# CMS/PKCS#7 key agreement algorithms & parameters + +class Gost28147_89_KeyWrapParameters(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('encryptionParamSet', Gost28147_89_ParamSet()), + namedtype.OptionalNamedType('ukm', univ.OctetString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(8, 8))) + ) + + +id_Gost28147_89_CryptoPro_KeyWrap = id_CryptoPro_algorithms + (13, 1, ) + + +id_Gost28147_89_None_KeyWrap = id_CryptoPro_algorithms + (13, 0, ) + + +id_GostR3410_2001_CryptoPro_ESDH = id_CryptoPro_algorithms + (96, ) + + +id_GostR3410_94_CryptoPro_ESDH = id_CryptoPro_algorithms + (97, ) + + +# CMS/PKCS#7 key transport algorithms & parameters + +id_GostR3410_2001_KeyTransportSMIMECapability = id_GostR3410_2001 + + +id_GostR3410_94_KeyTransportSMIMECapability = id_GostR3410_94 + + +class GostR3410_TransportParameters(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('encryptionParamSet', Gost28147_89_ParamSet()), + namedtype.OptionalNamedType('ephemeralPublicKey', + SubjectPublicKeyInfo().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('ukm', univ.OctetString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(8, 8))) + ) + +class GostR3410_KeyTransport(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('sessionEncryptedKey', Gost28147_89_EncryptedKey()), + namedtype.OptionalNamedType('transportParameters', + GostR3410_TransportParameters().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 0))) + ) + + +# GOST R 34.10-94 signature algorithm & parameters + +class GostR3410_94_Signature(univ.OctetString): + subtypeSpec = constraint.ValueSizeConstraint(64, 64) + + +# GOST R 34.10-2001 signature algorithms and parameters + +class GostR3410_2001_Signature(univ.OctetString): + subtypeSpec = constraint.ValueSizeConstraint(64, 64) + + +# Update the Algorithm Identifier map in rfc5280.py + +_algorithmIdentifierMapUpdate = { + id_Gost28147_89_CryptoPro_KeyWrap: Gost28147_89_KeyWrapParameters(), + id_Gost28147_89_None_KeyWrap: Gost28147_89_KeyWrapParameters(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc4491.py b/pyasn1_modules/rfc4491.py new file mode 100644 index 0000000..60b5560 --- /dev/null +++ b/pyasn1_modules/rfc4491.py @@ -0,0 +1,44 @@ +# +# 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 +# +# Using the GOST R 34.10-94, GOST R 34.10-2001, and GOST R 34.11-94 +# Algorithms with Certificates and CRLs +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc4491.txt +# + +from pyasn1_modules import rfc4357 + + +# Signature Algorithm GOST R 34.10-94 + +id_GostR3411_94_with_GostR3410_94 = rfc4357.id_GostR3411_94_with_GostR3410_94 + + +# Signature Algorithm GOST R 34.10-2001 + +id_GostR3411_94_with_GostR3410_2001 = rfc4357.id_GostR3411_94_with_GostR3410_2001 + + +# GOST R 34.10-94 Keys + +id_GostR3410_94 = rfc4357.id_GostR3410_94 + +GostR3410_2001_PublicKey = rfc4357.GostR3410_2001_PublicKey + +GostR3410_2001_PublicKeyParameters = rfc4357.GostR3410_2001_PublicKeyParameters + + +# GOST R 34.10-2001 Keys + +id_GostR3410_2001 = rfc4357.id_GostR3410_2001 + +GostR3410_94_PublicKey = rfc4357.GostR3410_94_PublicKey + +GostR3410_94_PublicKeyParameters = rfc4357.GostR3410_94_PublicKeyParameters diff --git a/pyasn1_modules/rfc4683.py b/pyasn1_modules/rfc4683.py new file mode 100644 index 0000000..11ac65a --- /dev/null +++ b/pyasn1_modules/rfc4683.py @@ -0,0 +1,72 @@ +# +# 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 +# +# Subject Identification Method (SIM) +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc4683.txt +# https://www.rfc-editor.org/errata/eid1047 +# + +from pyasn1.type import char +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +# Used to compute the PEPSI value + +class HashContent(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('userPassword', char.UTF8String()), + namedtype.NamedType('authorityRandom', univ.OctetString()), + namedtype.NamedType('identifierType', univ.ObjectIdentifier()), + namedtype.NamedType('identifier', char.UTF8String()) + ) + + +# Used to encode the PEPSI value as the SIM Other Name + +id_pkix = rfc5280.id_pkix + +id_on = id_pkix + (8,) + +id_on_SIM = id_on + (6,) + + +class SIM(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('hashAlg', rfc5280.AlgorithmIdentifier()), + namedtype.NamedType('authorityRandom', univ.OctetString()), + namedtype.NamedType('pEPSI', univ.OctetString()) + ) + + +# Used to encrypt the PEPSI value during certificate request + +id_pkip = id_pkix + (5,) + +id_regEPEPSI = id_pkip + (3,) + + +class EncryptedPEPSI(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('identifierType', univ.ObjectIdentifier()), + namedtype.NamedType('identifier', char.UTF8String()), + namedtype.NamedType('sIM', SIM()) + ) + + +# Update the map of Other Name OIDs to Other Names in rfc5280.py + +_anotherNameMapUpdate = { + id_on_SIM: SIM(), +} + +rfc5280.anotherNameMap.update(_anotherNameMapUpdate) diff --git a/pyasn1_modules/rfc4985.py b/pyasn1_modules/rfc4985.py new file mode 100644 index 0000000..318e412 --- /dev/null +++ b/pyasn1_modules/rfc4985.py @@ -0,0 +1,49 @@ +# +# 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 +# +# Expression of Service Names in X.509 Certificates +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc4985.txt +# + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + +MAX = float('inf') + + +# As specified in Appendix A.2 of RFC 4985 + +id_pkix = rfc5280.id_pkix + +id_on = id_pkix + (8, ) + +id_on_dnsSRV = id_on + (7, ) + + +class SRVName(char.IA5String): + subtypeSpec = constraint.ValueSizeConstraint(1, MAX) + + +srvName = rfc5280.AnotherName() +srvName['type-id'] = id_on_dnsSRV +srvName['value'] = SRVName() + + +# Map of Other Name OIDs to Other Name is added to the +# ones that are in rfc5280.py + +_anotherNameMapUpdate = { + id_on_dnsSRV: SRVName(), +} + +rfc5280.anotherNameMap.update(_anotherNameMapUpdate) diff --git a/pyasn1_modules/rfc5035.py b/pyasn1_modules/rfc5035.py new file mode 100644 index 0000000..1cec982 --- /dev/null +++ b/pyasn1_modules/rfc5035.py @@ -0,0 +1,199 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with assistance from asn1ate v.0.6.0. +# Modified by Russ Housley to add a map for use with opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Update to Enhanced Security Services for S/MIME +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5035.txt +# + +from pyasn1.codec.der.encoder import encode as der_encode + +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc2634 +from pyasn1_modules import rfc4055 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5280 + +ContentType = rfc5652.ContentType + +IssuerAndSerialNumber = rfc5652.IssuerAndSerialNumber + +SubjectKeyIdentifier = rfc5652.SubjectKeyIdentifier + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + +PolicyInformation = rfc5280.PolicyInformation + +GeneralNames = rfc5280.GeneralNames + +CertificateSerialNumber = rfc5280.CertificateSerialNumber + + +# Signing Certificate Attribute V1 and V2 + +id_aa_signingCertificate = rfc2634.id_aa_signingCertificate + +id_aa_signingCertificateV2 = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.47') + +Hash = rfc2634.Hash + +IssuerSerial = rfc2634.IssuerSerial + +ESSCertID = rfc2634.ESSCertID + +SigningCertificate = rfc2634.SigningCertificate + + +sha256AlgId = AlgorithmIdentifier() +sha256AlgId['algorithm'] = rfc4055.id_sha256 +# A non-schema object for sha256AlgId['parameters'] as absent +sha256AlgId['parameters'] = der_encode(univ.OctetString('')) + + +class ESSCertIDv2(univ.Sequence): + pass + +ESSCertIDv2.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('hashAlgorithm', sha256AlgId), + namedtype.NamedType('certHash', Hash()), + namedtype.OptionalNamedType('issuerSerial', IssuerSerial()) +) + + +class SigningCertificateV2(univ.Sequence): + pass + +SigningCertificateV2.componentType = namedtype.NamedTypes( + namedtype.NamedType('certs', univ.SequenceOf( + componentType=ESSCertIDv2())), + namedtype.OptionalNamedType('policies', univ.SequenceOf( + componentType=PolicyInformation())) +) + + +# Mail List Expansion History Attribute + +id_aa_mlExpandHistory = rfc2634.id_aa_mlExpandHistory + +ub_ml_expansion_history = rfc2634.ub_ml_expansion_history + +EntityIdentifier = rfc2634.EntityIdentifier + +MLReceiptPolicy = rfc2634.MLReceiptPolicy + +MLData = rfc2634.MLData + +MLExpansionHistory = rfc2634.MLExpansionHistory + + +# ESS Security Label Attribute + +id_aa_securityLabel = rfc2634.id_aa_securityLabel + +ub_privacy_mark_length = rfc2634.ub_privacy_mark_length + +ub_security_categories = rfc2634.ub_security_categories + +ub_integer_options = rfc2634.ub_integer_options + +ESSPrivacyMark = rfc2634.ESSPrivacyMark + +SecurityClassification = rfc2634.SecurityClassification + +SecurityPolicyIdentifier = rfc2634.SecurityPolicyIdentifier + +SecurityCategory = rfc2634.SecurityCategory + +SecurityCategories = rfc2634.SecurityCategories + +ESSSecurityLabel = rfc2634.ESSSecurityLabel + + +# Equivalent Labels Attribute + +id_aa_equivalentLabels = rfc2634.id_aa_equivalentLabels + +EquivalentLabels = rfc2634.EquivalentLabels + + +# Content Identifier Attribute + +id_aa_contentIdentifier = rfc2634.id_aa_contentIdentifier + +ContentIdentifier = rfc2634.ContentIdentifier + + +# Content Reference Attribute + +id_aa_contentReference = rfc2634.id_aa_contentReference + +ContentReference = rfc2634.ContentReference + + +# Message Signature Digest Attribute + +id_aa_msgSigDigest = rfc2634.id_aa_msgSigDigest + +MsgSigDigest = rfc2634.MsgSigDigest + + +# Content Hints Attribute + +id_aa_contentHint = rfc2634.id_aa_contentHint + +ContentHints = rfc2634.ContentHints + + +# Receipt Request Attribute + +AllOrFirstTier = rfc2634.AllOrFirstTier + +ReceiptsFrom = rfc2634.ReceiptsFrom + +id_aa_receiptRequest = rfc2634.id_aa_receiptRequest + +ub_receiptsTo = rfc2634.ub_receiptsTo + +ReceiptRequest = rfc2634.ReceiptRequest + + +# Receipt Content Type + +ESSVersion = rfc2634.ESSVersion + +id_ct_receipt = rfc2634.id_ct_receipt + +Receipt = rfc2634.Receipt + +ub_receiptsTo = rfc2634.ub_receiptsTo + +ReceiptRequest = rfc2634.ReceiptRequest + + +# Map of Attribute Type to the Attribute structure is added to the +# ones that are in rfc5652.py + +_cmsAttributesMapUpdate = { + id_aa_signingCertificateV2: SigningCertificateV2(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) + + +# Map of Content Type OIDs to Content Types is added to the +# ones that are in rfc5652.py + +_cmsContentTypesMapUpdate = { + id_ct_receipt: Receipt(), +} + +rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate) diff --git a/pyasn1_modules/rfc5083.py b/pyasn1_modules/rfc5083.py new file mode 100644 index 0000000..26ef550 --- /dev/null +++ b/pyasn1_modules/rfc5083.py @@ -0,0 +1,52 @@ +# This file is being contributed to of pyasn1-modules software. +# +# Created by Russ Housley without assistance from the asn1ate tool. +# Modified by Russ Housley to add a map for use with opentypes and +# simplify the code for the object identifier assignment. +# +# Copyright (c) 2018, 2019 Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Authenticated-Enveloped-Data for the Cryptographic Message Syntax (CMS) +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5083.txt + +from pyasn1.type import namedtype +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5652 + +MAX = float('inf') + + +# CMS Authenticated-Enveloped-Data Content Type + +id_ct_authEnvelopedData = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.23') + +class AuthEnvelopedData(univ.Sequence): + pass + +AuthEnvelopedData.componentType = namedtype.NamedTypes( + namedtype.NamedType('version', rfc5652.CMSVersion()), + namedtype.OptionalNamedType('originatorInfo', rfc5652.OriginatorInfo().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.NamedType('recipientInfos', rfc5652.RecipientInfos()), + namedtype.NamedType('authEncryptedContentInfo', rfc5652.EncryptedContentInfo()), + namedtype.OptionalNamedType('authAttrs', rfc5652.AuthAttributes().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('mac', rfc5652.MessageAuthenticationCode()), + namedtype.OptionalNamedType('unauthAttrs', rfc5652.UnauthAttributes().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) +) + + +# Map of Content Type OIDs to Content Types is added to the +# ones that are in rfc5652.py + +_cmsContentTypesMapUpdate = { + id_ct_authEnvelopedData: AuthEnvelopedData(), +} + +rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate) diff --git a/pyasn1_modules/rfc5084.py b/pyasn1_modules/rfc5084.py new file mode 100644 index 0000000..7686839 --- /dev/null +++ b/pyasn1_modules/rfc5084.py @@ -0,0 +1,97 @@ +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley with assistance from the asn1ate tool, with manual +# changes to AES_CCM_ICVlen.subtypeSpec and added comments +# +# Copyright (c) 2018-2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# AES-CCM and AES-GCM Algorithms fo use with the Authenticated-Enveloped-Data +# protecting content type for the Cryptographic Message Syntax (CMS) +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5084.txt + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +def _OID(*components): + output = [] + for x in tuple(components): + if isinstance(x, univ.ObjectIdentifier): + output.extend(list(x)) + else: + output.append(int(x)) + + return univ.ObjectIdentifier(output) + + +class AES_CCM_ICVlen(univ.Integer): + pass + + +class AES_GCM_ICVlen(univ.Integer): + pass + + +AES_CCM_ICVlen.subtypeSpec = constraint.SingleValueConstraint(4, 6, 8, 10, 12, 14, 16) + +AES_GCM_ICVlen.subtypeSpec = constraint.ValueRangeConstraint(12, 16) + + +class CCMParameters(univ.Sequence): + pass + + +CCMParameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('aes-nonce', univ.OctetString().subtype(subtypeSpec=constraint.ValueSizeConstraint(7, 13))), + # The aes-nonce parameter contains 15-L octets, where L is the size of the length field. L=8 is RECOMMENDED. + # Within the scope of any content-authenticated-encryption key, the nonce value MUST be unique. + namedtype.DefaultedNamedType('aes-ICVlen', AES_CCM_ICVlen().subtype(value=12)) +) + + +class GCMParameters(univ.Sequence): + pass + + +GCMParameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('aes-nonce', univ.OctetString()), + # The aes-nonce may have any number of bits between 8 and 2^64, but it MUST be a multiple of 8 bits. + # Within the scope of any content-authenticated-encryption key, the nonce value MUST be unique. + # A nonce value of 12 octets can be processed more efficiently, so that length is RECOMMENDED. + namedtype.DefaultedNamedType('aes-ICVlen', AES_GCM_ICVlen().subtype(value=12)) +) + +aes = _OID(2, 16, 840, 1, 101, 3, 4, 1) + +id_aes128_CCM = _OID(aes, 7) + +id_aes128_GCM = _OID(aes, 6) + +id_aes192_CCM = _OID(aes, 27) + +id_aes192_GCM = _OID(aes, 26) + +id_aes256_CCM = _OID(aes, 47) + +id_aes256_GCM = _OID(aes, 46) + + +# Map of Algorithm Identifier OIDs to Parameters is added to the +# ones in rfc5280.py + +_algorithmIdentifierMapUpdate = { + id_aes128_CCM: CCMParameters(), + id_aes128_GCM: GCMParameters(), + id_aes192_CCM: CCMParameters(), + id_aes192_GCM: GCMParameters(), + id_aes256_CCM: CCMParameters(), + id_aes256_GCM: GCMParameters(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc5126.py b/pyasn1_modules/rfc5126.py new file mode 100644 index 0000000..8e016c2 --- /dev/null +++ b/pyasn1_modules/rfc5126.py @@ -0,0 +1,577 @@ +# +# 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 +# +# CMS Advanced Electronic Signatures (CAdES) +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5126.txt +# + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import opentype +from pyasn1.type import tag +from pyasn1.type import useful +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5035 +from pyasn1_modules import rfc5755 +from pyasn1_modules import rfc6960 +from pyasn1_modules import rfc3161 + +MAX = float('inf') + + +# Maps for OpenTypes + +commitmentQualifierMap = { } + +sigQualifiersMap = { } + +otherRevRefMap = { } + +otherRevValMap = { } + + +# Imports from RFC 5652 + +ContentInfo = rfc5652.ContentInfo + +ContentType = rfc5652.ContentType + +SignedData = rfc5652.SignedData + +EncapsulatedContentInfo = rfc5652.EncapsulatedContentInfo + +SignerInfo = rfc5652.SignerInfo + +MessageDigest = rfc5652.MessageDigest + +SigningTime = rfc5652.SigningTime + +Countersignature = rfc5652.Countersignature + +id_data = rfc5652.id_data + +id_signedData = rfc5652.id_signedData + +id_contentType= rfc5652.id_contentType + +id_messageDigest = rfc5652.id_messageDigest + +id_signingTime = rfc5652.id_signingTime + +id_countersignature = rfc5652.id_countersignature + + +# Imports from RFC 5035 + +SigningCertificate = rfc5035.SigningCertificate + +IssuerSerial = rfc5035.IssuerSerial + +ContentReference = rfc5035.ContentReference + +ContentIdentifier = rfc5035.ContentIdentifier + +id_aa_contentReference = rfc5035.id_aa_contentReference + +id_aa_contentIdentifier = rfc5035.id_aa_contentIdentifier + +id_aa_signingCertificate = rfc5035.id_aa_signingCertificate + +id_aa_signingCertificateV2 = rfc5035.id_aa_signingCertificateV2 + + +# Imports from RFC 5280 + +Certificate = rfc5280.Certificate + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + +CertificateList = rfc5280.CertificateList + +Name = rfc5280.Name + +Attribute = rfc5280.Attribute + +GeneralNames = rfc5280.GeneralNames + +GeneralName = rfc5280.GeneralName + +PolicyInformation = rfc5280.PolicyInformation + +DirectoryString = rfc5280.DirectoryString + + +# Imports from RFC 5755 + +AttributeCertificate = rfc5755.AttributeCertificate + + +# Imports from RFC 6960 + +BasicOCSPResponse = rfc6960.BasicOCSPResponse + +ResponderID = rfc6960.ResponderID + + +# Imports from RFC 3161 + +TimeStampToken = rfc3161.TimeStampToken + + +# OID used referencing electronic signature mechanisms + +id_etsi_es_IDUP_Mechanism_v1 = univ.ObjectIdentifier('0.4.0.1733.1.4.1') + + +# OtherSigningCertificate - deprecated + +id_aa_ets_otherSigCert = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.19') + + +class OtherHashValue(univ.OctetString): + pass + + +class OtherHashAlgAndValue(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('hashAlgorithm', AlgorithmIdentifier()), + namedtype.NamedType('hashValue', OtherHashValue()) + ) + + +class OtherHash(univ.Choice): + componentType = namedtype.NamedTypes( + namedtype.NamedType('sha1Hash', OtherHashValue()), + namedtype.NamedType('otherHash', OtherHashAlgAndValue()) + ) + + +class OtherCertID(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('otherCertHash', OtherHash()), + namedtype.OptionalNamedType('issuerSerial', IssuerSerial()) + ) + + +class OtherSigningCertificate(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('certs', + univ.SequenceOf(componentType=OtherCertID())), + namedtype.OptionalNamedType('policies', + univ.SequenceOf(componentType=PolicyInformation())) + ) + + +# Signature Policy Identifier + +id_aa_ets_sigPolicyId = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.15') + + +class SigPolicyId(univ.ObjectIdentifier): + pass + + +class SigPolicyHash(OtherHashAlgAndValue): + pass + + +class SigPolicyQualifierId(univ.ObjectIdentifier): + pass + + +class SigPolicyQualifierInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('sigPolicyQualifierId', SigPolicyQualifierId()), + namedtype.NamedType('sigQualifier', univ.Any(), + openType=opentype.OpenType('sigPolicyQualifierId', sigQualifiersMap)) + ) + + +class SignaturePolicyId(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('sigPolicyId', SigPolicyId()), + namedtype.NamedType('sigPolicyHash', SigPolicyHash()), + namedtype.OptionalNamedType('sigPolicyQualifiers', + univ.SequenceOf(componentType=SigPolicyQualifierInfo()).subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, MAX))) + ) + + +class SignaturePolicyImplied(univ.Null): + pass + + +class SignaturePolicy(univ.Choice): + componentType = namedtype.NamedTypes( + namedtype.NamedType('signaturePolicyId', SignaturePolicyId()), + namedtype.NamedType('signaturePolicyImplied', SignaturePolicyImplied()) + ) + + +id_spq_ets_unotice = univ.ObjectIdentifier('1.2.840.113549.1.9.16.5.2') + + +class DisplayText(univ.Choice): + componentType = namedtype.NamedTypes( + namedtype.NamedType('visibleString', char.VisibleString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, 200))), + namedtype.NamedType('bmpString', char.BMPString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, 200))), + namedtype.NamedType('utf8String', char.UTF8String().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, 200))) + ) + + +class NoticeReference(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('organization', DisplayText()), + namedtype.NamedType('noticeNumbers', + univ.SequenceOf(componentType=univ.Integer())) + ) + +class SPUserNotice(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('noticeRef', NoticeReference()), + namedtype.OptionalNamedType('explicitText', DisplayText()) + ) + + +noticeToUser = SigPolicyQualifierInfo() +noticeToUser['sigPolicyQualifierId'] = id_spq_ets_unotice +noticeToUser['sigQualifier'] = SPUserNotice() + + +id_spq_ets_uri = univ.ObjectIdentifier('1.2.840.113549.1.9.16.5.1') + + +class SPuri(char.IA5String): + pass + + +pointerToSigPolSpec = SigPolicyQualifierInfo() +pointerToSigPolSpec['sigPolicyQualifierId'] = id_spq_ets_uri +pointerToSigPolSpec['sigQualifier'] = SPuri() + + +# Commitment Type + +id_aa_ets_commitmentType = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.16') + + +class CommitmentTypeIdentifier(univ.ObjectIdentifier): + pass + + +class CommitmentTypeQualifier(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('commitmentTypeIdentifier', + CommitmentTypeIdentifier()), + namedtype.NamedType('qualifier', univ.Any(), + openType=opentype.OpenType('commitmentTypeIdentifier', + commitmentQualifierMap)) + ) + + +class CommitmentTypeIndication(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('commitmentTypeId', CommitmentTypeIdentifier()), + namedtype.OptionalNamedType('commitmentTypeQualifier', + univ.SequenceOf(componentType=CommitmentTypeQualifier()).subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, MAX))) + ) + + +id_cti_ets_proofOfOrigin = univ.ObjectIdentifier('1.2.840.113549.1.9.16.6.1') + +id_cti_ets_proofOfReceipt = univ.ObjectIdentifier('1.2.840.113549.1.9.16.6.2') + +id_cti_ets_proofOfDelivery = univ.ObjectIdentifier('1.2.840.113549.1.9.16.6.3') + +id_cti_ets_proofOfSender = univ.ObjectIdentifier('1.2.840.113549.1.9.16.6.4') + +id_cti_ets_proofOfApproval = univ.ObjectIdentifier('1.2.840.113549.1.9.16.6.5') + +id_cti_ets_proofOfCreation = univ.ObjectIdentifier('1.2.840.113549.1.9.16.6.6') + + +# Signer Location + +id_aa_ets_signerLocation = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.17') + + +class PostalAddress(univ.SequenceOf): + componentType = DirectoryString() + subtypeSpec = constraint.ValueSizeConstraint(1, 6) + + +class SignerLocation(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('countryName', + DirectoryString().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('localityName', + DirectoryString().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('postalAdddress', + PostalAddress().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 2))) + ) + + +# Signature Timestamp + +id_aa_signatureTimeStampToken = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.14') + + +class SignatureTimeStampToken(TimeStampToken): + pass + + +# Content Timestamp + +id_aa_ets_contentTimestamp = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.20') + + +class ContentTimestamp(TimeStampToken): + pass + + +# Signer Attributes + +id_aa_ets_signerAttr = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.18') + + +class ClaimedAttributes(univ.SequenceOf): + componentType = Attribute() + + +class CertifiedAttributes(AttributeCertificate): + pass + + +class SignerAttribute(univ.SequenceOf): + componentType = univ.Choice(componentType=namedtype.NamedTypes( + namedtype.NamedType('claimedAttributes', + ClaimedAttributes().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('certifiedAttributes', + CertifiedAttributes().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))) + )) + + +# Complete Certificate Refs + +id_aa_ets_certificateRefs = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.21') + + +class CompleteCertificateRefs(univ.SequenceOf): + componentType = OtherCertID() + + +# Complete Revocation Refs + +id_aa_ets_revocationRefs = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.22') + + +class CrlIdentifier(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('crlissuer', Name()), + namedtype.NamedType('crlIssuedTime', useful.UTCTime()), + namedtype.OptionalNamedType('crlNumber', univ.Integer()) + ) + + +class CrlValidatedID(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('crlHash', OtherHash()), + namedtype.OptionalNamedType('crlIdentifier', CrlIdentifier()) + ) + + +class CRLListID(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('crls', + univ.SequenceOf(componentType=CrlValidatedID())) + ) + + +class OcspIdentifier(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('ocspResponderID', ResponderID()), + namedtype.NamedType('producedAt', useful.GeneralizedTime()) + ) + + +class OcspResponsesID(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('ocspIdentifier', OcspIdentifier()), + namedtype.OptionalNamedType('ocspRepHash', OtherHash()) + ) + + +class OcspListID(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('ocspResponses', + univ.SequenceOf(componentType=OcspResponsesID())) + ) + + +class OtherRevRefType(univ.ObjectIdentifier): + pass + + +class OtherRevRefs(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('otherRevRefType', OtherRevRefType()), + namedtype.NamedType('otherRevRefs', univ.Any(), + openType=opentype.OpenType('otherRevRefType', otherRevRefMap)) + ) + + +class CrlOcspRef(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('crlids', + CRLListID().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.OptionalNamedType('ocspids', + OcspListID().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 1))), + namedtype.OptionalNamedType('otherRev', + OtherRevRefs().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 2))) + ) + + +class CompleteRevocationRefs(univ.SequenceOf): + componentType = CrlOcspRef() + + +# Certificate Values + +id_aa_ets_certValues = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.23') + + +class CertificateValues(univ.SequenceOf): + componentType = Certificate() + + +# Certificate Revocation Values + +id_aa_ets_revocationValues = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.24') + + +class OtherRevValType(univ.ObjectIdentifier): + pass + + +class OtherRevVals(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('otherRevValType', OtherRevValType()), + namedtype.NamedType('otherRevVals', univ.Any(), + openType=opentype.OpenType('otherRevValType', otherRevValMap)) + ) + + +class RevocationValues(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('crlVals', + univ.SequenceOf(componentType=CertificateList()).subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('ocspVals', + univ.SequenceOf(componentType=BasicOCSPResponse()).subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('otherRevVals', + OtherRevVals().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 2))) + ) + + +# CAdES-C Timestamp + +id_aa_ets_escTimeStamp = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.25') + + +class ESCTimeStampToken(TimeStampToken): + pass + + +# Time-Stamped Certificates and CRLs + +id_aa_ets_certCRLTimestamp = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.26') + + +class TimestampedCertsCRLs(TimeStampToken): + pass + + +# Archive Timestamp + +id_aa_ets_archiveTimestampV2 = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.48') + + +class ArchiveTimeStampToken(TimeStampToken): + pass + + +# Attribute certificate references + +id_aa_ets_attrCertificateRefs = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.44') + + +class AttributeCertificateRefs(univ.SequenceOf): + componentType = OtherCertID() + + +# Attribute revocation references + +id_aa_ets_attrRevocationRefs = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.45') + + +class AttributeRevocationRefs(univ.SequenceOf): + componentType = CrlOcspRef() + + +# Update the sigQualifiersMap + +_sigQualifiersMapUpdate = { + id_spq_ets_unotice: SPUserNotice(), + id_spq_ets_uri: SPuri(), +} + +sigQualifiersMap.update(_sigQualifiersMapUpdate) + + +# Update the CMS Attribute Map in rfc5652.py + +_cmsAttributesMapUpdate = { + id_aa_ets_otherSigCert: OtherSigningCertificate(), + id_aa_ets_sigPolicyId: SignaturePolicy(), + id_aa_ets_commitmentType: CommitmentTypeIndication(), + id_aa_ets_signerLocation: SignerLocation(), + id_aa_signatureTimeStampToken: SignatureTimeStampToken(), + id_aa_ets_contentTimestamp: ContentTimestamp(), + id_aa_ets_signerAttr: SignerAttribute(), + id_aa_ets_certificateRefs: CompleteCertificateRefs(), + id_aa_ets_revocationRefs: CompleteRevocationRefs(), + id_aa_ets_certValues: CertificateValues(), + id_aa_ets_revocationValues: RevocationValues(), + id_aa_ets_escTimeStamp: ESCTimeStampToken(), + id_aa_ets_certCRLTimestamp: TimestampedCertsCRLs(), + id_aa_ets_archiveTimestampV2: ArchiveTimeStampToken(), + id_aa_ets_attrCertificateRefs: AttributeCertificateRefs(), + id_aa_ets_attrRevocationRefs: AttributeRevocationRefs(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) diff --git a/pyasn1_modules/rfc5208.py b/pyasn1_modules/rfc5208.py index 7857d2f..295fdbf 100644 --- a/pyasn1_modules/rfc5208.py +++ b/pyasn1_modules/rfc5208.py @@ -1,8 +1,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # PKCS#8 syntax # diff --git a/pyasn1_modules/rfc5275.py b/pyasn1_modules/rfc5275.py new file mode 100644 index 0000000..1be9598 --- /dev/null +++ b/pyasn1_modules/rfc5275.py @@ -0,0 +1,404 @@ +# +# 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 +# +# An Internet Attribute Certificate Profile for Authorization +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5275.txt +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import opentype +from pyasn1.type import tag +from pyasn1.type import univ +from pyasn1.type import useful + +from pyasn1_modules import rfc3565 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5751 +from pyasn1_modules import rfc5755 + +MAX = float('inf') + + +# Initialize the map for GLAQueryRequests and GLAQueryResponses + +glaQueryRRMap = { } + + +# Imports from RFC 3565 + +id_aes128_wrap = rfc3565.id_aes128_wrap + + +# Imports from RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + +Certificate = rfc5280.Certificate + +GeneralName = rfc5280.GeneralName + + +# Imports from RFC 5652 + +CertificateSet = rfc5652.CertificateSet + +KEKIdentifier = rfc5652.KEKIdentifier + +RecipientInfos = rfc5652.RecipientInfos + + +# Imports from RFC 5751 + +SMIMECapability = rfc5751.SMIMECapability + + +# Imports from RFC 5755 + +AttributeCertificate = rfc5755.AttributeCertificate + + +# The GL symmetric key distribution object identifier arc + +id_skd = univ.ObjectIdentifier((1, 2, 840, 113549, 1, 9, 16, 8,)) + + +# The GL Use KEK control attribute + +id_skd_glUseKEK = id_skd + (1,) + + +class Certificates(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('pKC', + Certificate().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('aC', + univ.SequenceOf(componentType=AttributeCertificate()).subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, MAX)).subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('certPath', + CertificateSet().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 2))) + ) + + +class GLInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('glName', GeneralName()), + namedtype.NamedType('glAddress', GeneralName()) + ) + + +class GLOwnerInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('glOwnerName', GeneralName()), + namedtype.NamedType('glOwnerAddress', GeneralName()), + namedtype.OptionalNamedType('certificates', Certificates()) + ) + + +class GLAdministration(univ.Integer): + namedValues = namedval.NamedValues( + ('unmanaged', 0), + ('managed', 1), + ('closed', 2) + ) + + +requested_algorithm = SMIMECapability().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)) +requested_algorithm['capabilityID'] = id_aes128_wrap + + +class GLKeyAttributes(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('rekeyControlledByGLO', + univ.Boolean().subtype(value=0, + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.DefaultedNamedType('recipientsNotMutuallyAware', + univ.Boolean().subtype(value=1, + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.DefaultedNamedType('duration', + univ.Integer().subtype(value=0, + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.DefaultedNamedType('generationCounter', + univ.Integer().subtype(value=2, + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.DefaultedNamedType('requestedAlgorithm', requested_algorithm) + ) + + +class GLUseKEK(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('glInfo', GLInfo()), + namedtype.NamedType('glOwnerInfo', + univ.SequenceOf(componentType=GLOwnerInfo()).subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, MAX))), + namedtype.DefaultedNamedType('glAdministration', + GLAdministration().subtype(value=1)), + namedtype.OptionalNamedType('glKeyAttributes', GLKeyAttributes()) + ) + + +# The Delete GL control attribute + +id_skd_glDelete = id_skd + (2,) + + +class DeleteGL(GeneralName): + pass + + +# The Add GL Member control attribute + +id_skd_glAddMember = id_skd + (3,) + + +class GLMember(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('glMemberName', GeneralName()), + namedtype.OptionalNamedType('glMemberAddress', GeneralName()), + namedtype.OptionalNamedType('certificates', Certificates()) + ) + + +class GLAddMember(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('glName', GeneralName()), + namedtype.NamedType('glMember', GLMember()) + ) + + +# The Delete GL Member control attribute + +id_skd_glDeleteMember = id_skd + (4,) + + +class GLDeleteMember(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('glName', GeneralName()), + namedtype.NamedType('glMemberToDelete', GeneralName()) + ) + + +# The GL Rekey control attribute + +id_skd_glRekey = id_skd + (5,) + + +class GLNewKeyAttributes(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('rekeyControlledByGLO', + univ.Boolean().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('recipientsNotMutuallyAware', + univ.Boolean().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('duration', + univ.Integer().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.OptionalNamedType('generationCounter', + univ.Integer().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.OptionalNamedType('requestedAlgorithm', + AlgorithmIdentifier().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 4))) + ) + + +class GLRekey(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('glName', GeneralName()), + namedtype.OptionalNamedType('glAdministration', GLAdministration()), + namedtype.OptionalNamedType('glNewKeyAttributes', GLNewKeyAttributes()), + namedtype.OptionalNamedType('glRekeyAllGLKeys', univ.Boolean()) + ) + + +# The Add and Delete GL Owner control attributes + +id_skd_glAddOwner = id_skd + (6,) + +id_skd_glRemoveOwner = id_skd + (7,) + + +class GLOwnerAdministration(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('glName', GeneralName()), + namedtype.NamedType('glOwnerInfo', GLOwnerInfo()) + ) + + +# The GL Key Compromise control attribute + +id_skd_glKeyCompromise = id_skd + (8,) + + +class GLKCompromise(GeneralName): + pass + + +# The GL Key Refresh control attribute + +id_skd_glkRefresh = id_skd + (9,) + + +class Date(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('start', useful.GeneralizedTime()), + namedtype.OptionalNamedType('end', useful.GeneralizedTime()) + ) + + +class GLKRefresh(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('glName', GeneralName()), + namedtype.NamedType('dates', + univ.SequenceOf(componentType=Date()).subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, MAX))) + ) + + +# The GLA Query Request control attribute + +id_skd_glaQueryRequest = id_skd + (11,) + + +class GLAQueryRequest(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('glaRequestType', univ.ObjectIdentifier()), + namedtype.NamedType('glaRequestValue', univ.Any(), + openType=opentype.OpenType('glaRequestType', glaQueryRRMap)) + ) + + +# The GLA Query Response control attribute + +id_skd_glaQueryResponse = id_skd + (12,) + + +class GLAQueryResponse(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('glaResponseType', univ.ObjectIdentifier()), + namedtype.NamedType('glaResponseValue', univ.Any(), + openType=opentype.OpenType('glaResponseType', glaQueryRRMap)) + ) + + +# The GLA Request/Response (glaRR) arc for glaRequestType/glaResponseType + +id_cmc_glaRR = univ.ObjectIdentifier((1, 3, 6, 1, 5, 5, 7, 7, 99,)) + + +# The Algorithm Request + +id_cmc_gla_skdAlgRequest = id_cmc_glaRR + (1,) + + +class SKDAlgRequest(univ.Null): + pass + + +# The Algorithm Response + +id_cmc_gla_skdAlgResponse = id_cmc_glaRR + (2,) + +SMIMECapabilities = rfc5751.SMIMECapabilities + + +# The control attribute to request an updated certificate to the GLA and +# the control attribute to return an updated certificate to the GLA + +id_skd_glProvideCert = id_skd + (13,) + +id_skd_glManageCert = id_skd + (14,) + + +class GLManageCert(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('glName', GeneralName()), + namedtype.NamedType('glMember', GLMember()) + ) + + +# The control attribute to distribute the GL shared KEK + +id_skd_glKey = id_skd + (15,) + + +class GLKey(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('glName', GeneralName()), + namedtype.NamedType('glIdentifier', KEKIdentifier()), + namedtype.NamedType('glkWrapped', RecipientInfos()), + namedtype.NamedType('glkAlgorithm', AlgorithmIdentifier()), + namedtype.NamedType('glkNotBefore', useful.GeneralizedTime()), + namedtype.NamedType('glkNotAfter', useful.GeneralizedTime()) + ) + + +# The CMC error types + +id_cet_skdFailInfo = univ.ObjectIdentifier((1, 3, 6, 1, 5, 5, 7, 15, 1,)) + + +class SKDFailInfo(univ.Integer): + namedValues = namedval.NamedValues( + ('unspecified', 0), + ('closedGL', 1), + ('unsupportedDuration', 2), + ('noGLACertificate', 3), + ('invalidCert', 4), + ('unsupportedAlgorithm', 5), + ('noGLONameMatch', 6), + ('invalidGLName', 7), + ('nameAlreadyInUse', 8), + ('noSpam', 9), + ('alreadyAMember', 11), + ('notAMember', 12), + ('alreadyAnOwner', 13), + ('notAnOwner', 14) + ) + + +# Update the map for GLAQueryRequests and GLAQueryResponses + +_glaQueryRRMapUpdate = { + id_cmc_gla_skdAlgRequest: univ.Null(""), + id_cmc_gla_skdAlgResponse: SMIMECapabilities(), +} + +glaQueryRRMap.update(_glaQueryRRMapUpdate) + + +# Update the map for CMC control attributes; since CMS Attributes and +# CMC Controls both use 'attrType', one map is used for both + +_cmcControlAttributesMapUpdate = { + id_skd_glUseKEK: GLUseKEK(), + id_skd_glDelete: DeleteGL(), + id_skd_glAddMember: GLAddMember(), + id_skd_glDeleteMember: GLDeleteMember(), + id_skd_glRekey: GLRekey(), + id_skd_glAddOwner: GLOwnerAdministration(), + id_skd_glRemoveOwner: GLOwnerAdministration(), + id_skd_glKeyCompromise: GLKCompromise(), + id_skd_glkRefresh: GLKRefresh(), + id_skd_glaQueryRequest: GLAQueryRequest(), + id_skd_glaQueryResponse: GLAQueryResponse(), + id_skd_glProvideCert: GLManageCert(), + id_skd_glManageCert: GLManageCert(), + id_skd_glKey: GLKey(), +} + +rfc5652.cmsAttributesMap.update(_cmcControlAttributesMapUpdate) diff --git a/pyasn1_modules/rfc5280.py b/pyasn1_modules/rfc5280.py index 2ecc627..ed5d28f 100644 --- a/pyasn1_modules/rfc5280.py +++ b/pyasn1_modules/rfc5280.py @@ -3,14 +3,17 @@ # This file is part of pyasn1-modules software. # # Created by Stanisław Pitucha with asn1ate tool. -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Updated by Russ Housley for ORAddress Extension Attribute opentype support. +# Updated by Russ Housley for AlgorithmIdentifier opentype support. +# +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Internet X.509 Public Key Infrastructure Certificate and Certificate # Revocation List (CRL) Profile # # ASN.1 source from: -# http://www.ietf.org/rfc/rfc5280.txt +# https://www.rfc-editor.org/rfc/rfc5280.txt # from pyasn1.type import char from pyasn1.type import constraint @@ -72,7 +75,7 @@ class Extensions(univ.SequenceOf): Extensions.componentType = Extension() -Extensions.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +Extensions.sizeSpec = constraint.ValueSizeConstraint(1, MAX) physical_delivery_personal_name = univ.Integer(13) @@ -203,7 +206,7 @@ class TeletexDomainDefinedAttributes(univ.SequenceOf): TeletexDomainDefinedAttributes.componentType = TeletexDomainDefinedAttribute() -TeletexDomainDefinedAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, ub_domain_defined_attributes) +TeletexDomainDefinedAttributes.sizeSpec = constraint.ValueSizeConstraint(1, ub_domain_defined_attributes) extended_network_address = univ.Integer(22) @@ -280,10 +283,15 @@ class CertificateSerialNumber(univ.Integer): pass +algorithmIdentifierMap = {} + + class AlgorithmIdentifier(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.NamedType('algorithm', univ.ObjectIdentifier()), - namedtype.OptionalNamedType('parameters', univ.Any()) + namedtype.OptionalNamedType('parameters', univ.Any(), + openType=opentype.OpenType('algorithm', algorithmIdentifierMap) + ) ) @@ -319,7 +327,7 @@ class RelativeDistinguishedName(univ.SetOf): RelativeDistinguishedName.componentType = AttributeTypeAndValue() -RelativeDistinguishedName.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +RelativeDistinguishedName.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class RDNSequence(univ.SequenceOf): @@ -382,7 +390,9 @@ class PhysicalDeliveryOfficeName(PDSParameter): ub_extension_attributes = univ.Integer(256) certificateExtensionsMap = { +} +oraddressExtensionAttributeMap = { } @@ -394,7 +404,7 @@ class ExtensionAttribute(univ.Sequence): namedtype.NamedType( 'extension-attribute-value', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)), - openType=opentype.OpenType('type', certificateExtensionsMap)) + openType=opentype.OpenType('extension-attribute-type', oraddressExtensionAttributeMap)) ) id_qt = _buildOid(id_pkix, 2) @@ -639,7 +649,7 @@ class ExtensionAttributes(univ.SetOf): ExtensionAttributes.componentType = ExtensionAttribute() -ExtensionAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, ub_extension_attributes) +ExtensionAttributes.sizeSpec = constraint.ValueSizeConstraint(1, ub_extension_attributes) ub_emailaddress_length = univ.Integer(255) @@ -786,7 +796,7 @@ class BuiltInDomainDefinedAttributes(univ.SequenceOf): BuiltInDomainDefinedAttributes.componentType = BuiltInDomainDefinedAttribute() -BuiltInDomainDefinedAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, ub_domain_defined_attributes) +BuiltInDomainDefinedAttributes.sizeSpec = constraint.ValueSizeConstraint(1, ub_domain_defined_attributes) id_at_pseudonym = _buildOid(id_at, 65) @@ -867,7 +877,7 @@ class OrganizationalUnitNames(univ.SequenceOf): OrganizationalUnitNames.componentType = OrganizationalUnitName() -OrganizationalUnitNames.subtypeSpec = constraint.ValueSizeConstraint(1, ub_organizational_units) +OrganizationalUnitNames.sizeSpec = constraint.ValueSizeConstraint(1, ub_organizational_units) class PrivateDomainName(univ.Choice): @@ -1026,7 +1036,7 @@ class TeletexOrganizationalUnitNames(univ.SequenceOf): TeletexOrganizationalUnitNames.componentType = TeletexOrganizationalUnitName() -TeletexOrganizationalUnitNames.subtypeSpec = constraint.ValueSizeConstraint(1, ub_organizational_units) +TeletexOrganizationalUnitNames.sizeSpec = constraint.ValueSizeConstraint(1, ub_organizational_units) id_ce = _buildOid(2, 5, 29) @@ -1149,7 +1159,7 @@ class GeneralNames(univ.SequenceOf): GeneralNames.componentType = GeneralName() -GeneralNames.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +GeneralNames.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class DistributionPointName(univ.Choice): @@ -1249,7 +1259,7 @@ class CRLDistributionPoints(univ.SequenceOf): CRLDistributionPoints.componentType = DistributionPoint() -CRLDistributionPoints.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +CRLDistributionPoints.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class GeneralSubtrees(univ.SequenceOf): @@ -1257,7 +1267,7 @@ class GeneralSubtrees(univ.SequenceOf): GeneralSubtrees.componentType = GeneralSubtree() -GeneralSubtrees.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +GeneralSubtrees.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class NameConstraints(univ.Sequence): @@ -1277,7 +1287,7 @@ class SubjectDirectoryAttributes(univ.SequenceOf): SubjectDirectoryAttributes.componentType = Attribute() -SubjectDirectoryAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +SubjectDirectoryAttributes.sizeSpec = constraint.ValueSizeConstraint(1, MAX) id_kp_OCSPSigning = _buildOid(id_kp, 9) @@ -1355,7 +1365,7 @@ class CertificatePolicies(univ.SequenceOf): CertificatePolicies.componentType = PolicyInformation() -CertificatePolicies.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +CertificatePolicies.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class SubjectAltName(GeneralNames): @@ -1393,7 +1403,7 @@ class PolicyMappings(univ.SequenceOf): ) ) -PolicyMappings.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +PolicyMappings.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class InhibitAnyPolicy(SkipCerts): @@ -1457,7 +1467,7 @@ class AuthorityInfoAccessSyntax(univ.SequenceOf): AuthorityInfoAccessSyntax.componentType = AccessDescription() -AuthorityInfoAccessSyntax.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +AuthorityInfoAccessSyntax.sizeSpec = constraint.ValueSizeConstraint(1, MAX) id_holdinstruction_none = _buildOid(holdInstruction, 1) @@ -1485,7 +1495,7 @@ class ExtKeyUsageSyntax(univ.SequenceOf): ExtKeyUsageSyntax.componentType = KeyPurposeId() -ExtKeyUsageSyntax.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +ExtKeyUsageSyntax.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class HoldInstructionCode(univ.ObjectIdentifier): @@ -1504,7 +1514,7 @@ class SubjectInfoAccessSyntax(univ.SequenceOf): SubjectInfoAccessSyntax.componentType = AccessDescription() -SubjectInfoAccessSyntax.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +SubjectInfoAccessSyntax.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class InvalidityDate(useful.GeneralizedTime): @@ -1562,6 +1572,37 @@ class PolicyConstraints(univ.Sequence): id_ce_inhibitAnyPolicy = _buildOid(id_ce, 54) +# map of ORAddress ExtensionAttribute type to ExtensionAttribute value + +_oraddressExtensionAttributeMapUpdate = { + common_name: CommonName(), + teletex_common_name: TeletexCommonName(), + teletex_organization_name: TeletexOrganizationName(), + teletex_personal_name: TeletexPersonalName(), + teletex_organizational_unit_names: TeletexOrganizationalUnitNames(), + pds_name: PDSName(), + physical_delivery_country_name: PhysicalDeliveryCountryName(), + postal_code: PostalCode(), + physical_delivery_office_name: PhysicalDeliveryOfficeName(), + physical_delivery_office_number: PhysicalDeliveryOfficeNumber(), + extension_OR_address_components: ExtensionORAddressComponents(), + physical_delivery_personal_name: PhysicalDeliveryPersonalName(), + physical_delivery_organization_name: PhysicalDeliveryOrganizationName(), + extension_physical_delivery_address_components: ExtensionPhysicalDeliveryAddressComponents(), + unformatted_postal_address: UnformattedPostalAddress(), + street_address: StreetAddress(), + post_office_box_address: PostOfficeBoxAddress(), + poste_restante_address: PosteRestanteAddress(), + unique_postal_name: UniquePostalName(), + local_postal_attributes: LocalPostalAttributes(), + extended_network_address: ExtendedNetworkAddress(), + terminal_type: TerminalType(), + teletex_domain_defined_attributes: TeletexDomainDefinedAttributes(), +} + +oraddressExtensionAttributeMap.update(_oraddressExtensionAttributeMapUpdate) + + # map of AttributeType -> AttributeValue _certificateAttributesMapUpdate = { @@ -1594,7 +1635,7 @@ class PolicyConstraints(univ.Sequence): id_ce_subjectKeyIdentifier: SubjectKeyIdentifier(), id_ce_keyUsage: KeyUsage(), id_ce_privateKeyUsagePeriod: PrivateKeyUsagePeriod(), - id_ce_certificatePolicies: PolicyInformation(), # could be a sequence of concat'ed objects? + id_ce_certificatePolicies: CertificatePolicies(), id_ce_policyMappings: PolicyMappings(), id_ce_subjectAltName: SubjectAltName(), id_ce_issuerAltName: IssuerAltName(), diff --git a/pyasn1_modules/rfc5480.py b/pyasn1_modules/rfc5480.py new file mode 100644 index 0000000..84c0c11 --- /dev/null +++ b/pyasn1_modules/rfc5480.py @@ -0,0 +1,190 @@ +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley with assistance from asn1ate v.0.6.0. +# Modified by Russ Housley to add maps for opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Elliptic Curve Cryptography Subject Public Key Information +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5480.txt + + +# What can be imported from rfc4055.py ? + +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc3279 +from pyasn1_modules import rfc5280 + + +# These structures are the same as RFC 3279. + +DHPublicKey = rfc3279.DHPublicKey + +DSAPublicKey = rfc3279.DSAPublicKey + +ValidationParms = rfc3279.ValidationParms + +DomainParameters = rfc3279.DomainParameters + +ECDSA_Sig_Value = rfc3279.ECDSA_Sig_Value + +ECPoint = rfc3279.ECPoint + +KEA_Parms_Id = rfc3279.KEA_Parms_Id + +RSAPublicKey = rfc3279.RSAPublicKey + + +# RFC 5480 changed the names of these structures from RFC 3279. + +DSS_Parms = rfc3279.Dss_Parms + +DSA_Sig_Value = rfc3279.Dss_Sig_Value + + +# RFC 3279 defines a more complex alternative for ECParameters. +# RFC 5480 narrows the definition to a single CHOICE: namedCurve. + +class ECParameters(univ.Choice): + pass + +ECParameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('namedCurve', univ.ObjectIdentifier()) +) + + +# OIDs for Message Digest Algorithms + +id_md2 = univ.ObjectIdentifier('1.2.840.113549.2.2') + +id_md5 = univ.ObjectIdentifier('1.2.840.113549.2.5') + +id_sha1 = univ.ObjectIdentifier('1.3.14.3.2.26') + +id_sha224 = univ.ObjectIdentifier('2.16.840.1.101.3.4.2.4') + +id_sha256 = univ.ObjectIdentifier('2.16.840.1.101.3.4.2.1') + +id_sha384 = univ.ObjectIdentifier('2.16.840.1.101.3.4.2.2') + +id_sha512 = univ.ObjectIdentifier('2.16.840.1.101.3.4.2.3') + + +# OID for RSA PK Algorithm and Key + +rsaEncryption = univ.ObjectIdentifier('1.2.840.113549.1.1.1') + + +# OID for DSA PK Algorithm, Key, and Parameters + +id_dsa = univ.ObjectIdentifier('1.2.840.10040.4.1') + + +# OID for Diffie-Hellman PK Algorithm, Key, and Parameters + +dhpublicnumber = univ.ObjectIdentifier('1.2.840.10046.2.1') + +# OID for KEA PK Algorithm and Parameters + +id_keyExchangeAlgorithm = univ.ObjectIdentifier('2.16.840.1.101.2.1.1.22') + + +# OIDs for Elliptic Curve Algorithm ID, Key, and Parameters +# Note that ECDSA keys always use this OID + +id_ecPublicKey = univ.ObjectIdentifier('1.2.840.10045.2.1') + +id_ecDH = univ.ObjectIdentifier('1.3.132.1.12') + +id_ecMQV = univ.ObjectIdentifier('1.3.132.1.13') + + +# OIDs for RSA Signature Algorithms + +md2WithRSAEncryption = univ.ObjectIdentifier('1.2.840.113549.1.1.2') + +md5WithRSAEncryption = univ.ObjectIdentifier('1.2.840.113549.1.1.4') + +sha1WithRSAEncryption = univ.ObjectIdentifier('1.2.840.113549.1.1.5') + + +# OIDs for DSA Signature Algorithms + +id_dsa_with_sha1 = univ.ObjectIdentifier('1.2.840.10040.4.3') + +id_dsa_with_sha224 = univ.ObjectIdentifier('2.16.840.1.101.3.4.3.1') + +id_dsa_with_sha256 = univ.ObjectIdentifier('2.16.840.1.101.3.4.3.2') + + +# OIDs for ECDSA Signature Algorithms + +ecdsa_with_SHA1 = univ.ObjectIdentifier('1.2.840.10045.4.1') + +ecdsa_with_SHA224 = univ.ObjectIdentifier('1.2.840.10045.4.3.1') + +ecdsa_with_SHA256 = univ.ObjectIdentifier('1.2.840.10045.4.3.2') + +ecdsa_with_SHA384 = univ.ObjectIdentifier('1.2.840.10045.4.3.3') + +ecdsa_with_SHA512 = univ.ObjectIdentifier('1.2.840.10045.4.3.4') + + +# OIDs for Named Elliptic Curves + +secp192r1 = univ.ObjectIdentifier('1.2.840.10045.3.1.1') + +sect163k1 = univ.ObjectIdentifier('1.3.132.0.1') + +sect163r2 = univ.ObjectIdentifier('1.3.132.0.15') + +secp224r1 = univ.ObjectIdentifier('1.3.132.0.33') + +sect233k1 = univ.ObjectIdentifier('1.3.132.0.26') + +sect233r1 = univ.ObjectIdentifier('1.3.132.0.27') + +secp256r1 = univ.ObjectIdentifier('1.2.840.10045.3.1.7') + +sect283k1 = univ.ObjectIdentifier('1.3.132.0.16') + +sect283r1 = univ.ObjectIdentifier('1.3.132.0.17') + +secp384r1 = univ.ObjectIdentifier('1.3.132.0.34') + +sect409k1 = univ.ObjectIdentifier('1.3.132.0.36') + +sect409r1 = univ.ObjectIdentifier('1.3.132.0.37') + +secp521r1 = univ.ObjectIdentifier('1.3.132.0.35') + +sect571k1 = univ.ObjectIdentifier('1.3.132.0.38') + +sect571r1 = univ.ObjectIdentifier('1.3.132.0.39') + + +# Map of Algorithm Identifier OIDs to Parameters +# The algorithm is not included if the parameters MUST be absent + +_algorithmIdentifierMapUpdate = { + rsaEncryption: univ.Null(), + md2WithRSAEncryption: univ.Null(), + md5WithRSAEncryption: univ.Null(), + sha1WithRSAEncryption: univ.Null(), + id_dsa: DSS_Parms(), + dhpublicnumber: DomainParameters(), + id_keyExchangeAlgorithm: KEA_Parms_Id(), + id_ecPublicKey: ECParameters(), + id_ecDH: ECParameters(), + id_ecMQV: ECParameters(), +} + + +# Add these Algorithm Identifier map entries to the ones in rfc5280.py + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc5636.py b/pyasn1_modules/rfc5636.py new file mode 100644 index 0000000..f87bc4e --- /dev/null +++ b/pyasn1_modules/rfc5636.py @@ -0,0 +1,113 @@ +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Traceable Anonymous Certificate +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5480.txt + +from pyasn1.type import namedtype +from pyasn1.type import univ +from pyasn1.type import useful + +from pyasn1_modules import rfc5652 + + +# Imports from RFC 5652 + +ContentInfo = rfc5652.ContentInfo + +EncapsulatedContentInfo = rfc5652.EncapsulatedContentInfo + +id_data = rfc5652.id_data + + +# Object Identifiers + +id_KISA = univ.ObjectIdentifier((1, 2, 410, 200004,)) + + +id_npki = id_KISA + (10,) + + +id_attribute = id_npki + (1,) + + +id_kisa_tac = id_attribute + (1,) + + +id_kisa_tac_token = id_kisa_tac + (1,) + + +id_kisa_tac_tokenandblindbash = id_kisa_tac + (2,) + + +id_kisa_tac_tokenandpartially = id_kisa_tac + (3,) + + +# Structures for Traceable Anonymous Certificate (TAC) + +class UserKey(univ.OctetString): + pass + + +class Timeout(useful.GeneralizedTime): + pass + + +class BlinedCertificateHash(univ.OctetString): + pass + + +class PartiallySignedCertificateHash(univ.OctetString): + pass + + +class Token(ContentInfo): + pass + + +class TokenandBlindHash(ContentInfo): + pass + + +class TokenandPartiallySignedCertificateHash(ContentInfo): + pass + + +# Added to the module in RFC 5636 for the CMS Content Type Map + +class TACToken(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('userKey', UserKey()), + namedtype.NamedType('timeout', Timeout()) + ) + + +class TACTokenandBlindHash(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('token', Token()), + namedtype.NamedType('blinded', BlinedCertificateHash()) + ) + + +class TACTokenandPartiallySignedCertificateHash(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('token', Token()), + namedtype.NamedType('partially', PartiallySignedCertificateHash()) + ) + + +# Add to the CMS Content Type Map in rfc5752.py + +_cmsContentTypesMapUpdate = { + id_kisa_tac_token: TACToken(), + id_kisa_tac_tokenandblindbash: TACTokenandBlindHash(), + id_kisa_tac_tokenandpartially: TACTokenandPartiallySignedCertificateHash(), +} + +rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate) diff --git a/pyasn1_modules/rfc5639.py b/pyasn1_modules/rfc5639.py new file mode 100644 index 0000000..d48d300 --- /dev/null +++ b/pyasn1_modules/rfc5639.py @@ -0,0 +1,49 @@ +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Elliptic Curve Cryptography Brainpool Standard Curves +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5639.txt + + +from pyasn1.type import univ + + +ecStdCurvesAndGeneration = univ.ObjectIdentifier((1, 3, 36, 3, 3, 2, 8,)) + +ellipticCurve = ecStdCurvesAndGeneration + (1,) + +versionOne = ellipticCurve + (1,) + +brainpoolP160r1 = versionOne + (1,) + +brainpoolP160t1 = versionOne + (2,) + +brainpoolP192r1 = versionOne + (3,) + +brainpoolP192t1 = versionOne + (4,) + +brainpoolP224r1 = versionOne + (5,) + +brainpoolP224t1 = versionOne + (6,) + +brainpoolP256r1 = versionOne + (7,) + +brainpoolP256t1 = versionOne + (8,) + +brainpoolP320r1 = versionOne + (9,) + +brainpoolP320t1 = versionOne + (10,) + +brainpoolP384r1 = versionOne + (11,) + +brainpoolP384t1 = versionOne + (12,) + +brainpoolP512r1 = versionOne + (13,) + +brainpoolP512t1 = versionOne + (14,) diff --git a/pyasn1_modules/rfc5649.py b/pyasn1_modules/rfc5649.py new file mode 100644 index 0000000..84809ee --- /dev/null +++ b/pyasn1_modules/rfc5649.py @@ -0,0 +1,33 @@ +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# AES Key Wrap with Padding +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5649.txt + +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +class AlgorithmIdentifier(rfc5280.AlgorithmIdentifier): + pass + + +id_aes128_wrap = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.5') + +id_aes192_wrap = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.25') + +id_aes256_wrap = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.45') + + +id_aes128_wrap_pad = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.8') + +id_aes192_wrap_pad = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.28') + +id_aes256_wrap_pad = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.48') diff --git a/pyasn1_modules/rfc5652.py b/pyasn1_modules/rfc5652.py index 5fd5b79..1e95829 100644 --- a/pyasn1_modules/rfc5652.py +++ b/pyasn1_modules/rfc5652.py @@ -3,8 +3,10 @@ # This file is part of pyasn1-modules software. # # Created by Stanisław Pitucha with asn1ate tool. -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Modified by Russ Housley to add support for opentypes. +# +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Cryptographic Message Syntax (CMS) # @@ -14,6 +16,7 @@ from pyasn1.type import constraint from pyasn1.type import namedtype from pyasn1.type import namedval +from pyasn1.type import opentype from pyasn1.type import tag from pyasn1.type import univ from pyasn1.type import useful @@ -35,6 +38,19 @@ def _buildOid(*components): return univ.ObjectIdentifier(output) +cmsContentTypesMap = { } + +cmsAttributesMap = { } + +otherKeyAttributesMap = { } + +otherCertFormatMap = { } + +otherRevInfoFormatMap = { } + +otherRecipientInfoMap = { } + + class AttCertVersionV1(univ.Integer): pass @@ -89,7 +105,9 @@ class Attribute(univ.Sequence): Attribute.componentType = namedtype.NamedTypes( namedtype.NamedType('attrType', univ.ObjectIdentifier()), - namedtype.NamedType('attrValues', univ.SetOf(componentType=AttributeValue())) + namedtype.NamedType('attrValues', univ.SetOf(componentType=AttributeValue()), + openType=opentype.OpenType('attrType', cmsAttributesMap) + ) ) @@ -98,7 +116,7 @@ class SignedAttributes(univ.SetOf): SignedAttributes.componentType = Attribute() -SignedAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +SignedAttributes.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class AttributeCertificateV2(rfc3281.AttributeCertificate): @@ -111,7 +129,9 @@ class OtherKeyAttribute(univ.Sequence): OtherKeyAttribute.componentType = namedtype.NamedTypes( namedtype.NamedType('keyAttrId', univ.ObjectIdentifier()), - namedtype.OptionalNamedType('keyAttr', univ.Any()) + namedtype.OptionalNamedType('keyAttr', univ.Any(), + openType=opentype.OpenType('keyAttrId', otherKeyAttributesMap) + ) ) @@ -120,7 +140,7 @@ class UnauthAttributes(univ.SetOf): UnauthAttributes.componentType = Attribute() -UnauthAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +UnauthAttributes.sizeSpec = constraint.ValueSizeConstraint(1, MAX) id_encryptedData = _buildOid(1, 2, 840, 113549, 1, 7, 6) @@ -210,7 +230,9 @@ class OtherCertificateFormat(univ.Sequence): OtherCertificateFormat.componentType = namedtype.NamedTypes( namedtype.NamedType('otherCertFormat', univ.ObjectIdentifier()), - namedtype.NamedType('otherCert', univ.Any()) + namedtype.NamedType('otherCert', univ.Any(), + openType=opentype.OpenType('otherCertFormat', otherCertFormatMap) + ) ) @@ -274,7 +296,9 @@ class OtherRevocationInfoFormat(univ.Sequence): OtherRevocationInfoFormat.componentType = namedtype.NamedTypes( namedtype.NamedType('otherRevInfoFormat', univ.ObjectIdentifier()), - namedtype.NamedType('otherRevInfo', univ.Any()) + namedtype.NamedType('otherRevInfo', univ.Any(), + openType=opentype.OpenType('otherRevInfoFormat', otherRevInfoFormatMap) + ) ) @@ -337,7 +361,7 @@ class UnprotectedAttributes(univ.SetOf): UnprotectedAttributes.componentType = Attribute() -UnprotectedAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +UnprotectedAttributes.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class KeyEncryptionAlgorithmIdentifier(rfc5280.AlgorithmIdentifier): @@ -455,7 +479,9 @@ class OtherRecipientInfo(univ.Sequence): OtherRecipientInfo.componentType = namedtype.NamedTypes( namedtype.NamedType('oriType', univ.ObjectIdentifier()), - namedtype.NamedType('oriValue', univ.Any()) + namedtype.NamedType('oriValue', univ.Any(), + openType=opentype.OpenType('oriType', otherRecipientInfoMap) + ) ) @@ -481,7 +507,7 @@ class RecipientInfos(univ.SetOf): RecipientInfos.componentType = RecipientInfo() -RecipientInfos.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +RecipientInfos.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class EnvelopedData(univ.Sequence): @@ -533,7 +559,7 @@ class UnsignedAttributes(univ.SetOf): UnsignedAttributes.componentType = Attribute() -UnsignedAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +UnsignedAttributes.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class SignerIdentifier(univ.Choice): @@ -581,7 +607,9 @@ class ContentInfo(univ.Sequence): ContentInfo.componentType = namedtype.NamedTypes( namedtype.NamedType('contentType', ContentType()), - namedtype.NamedType('content', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) + namedtype.NamedType('content', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)), + openType=opentype.OpenType('contentType', cmsContentTypesMap) + ) ) @@ -609,7 +637,7 @@ class AuthAttributes(univ.SetOf): AuthAttributes.componentType = Attribute() -AuthAttributes.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +AuthAttributes.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class Time(univ.Choice): @@ -704,3 +732,30 @@ class SigningTime(Time): id_ct_authData = _buildOid(1, 2, 840, 113549, 1, 9, 16, 1, 2) + + +# CMS Content Type Map + +_cmsContentTypesMapUpdate = { + id_ct_contentInfo: ContentInfo(), + id_data: univ.OctetString(), + id_signedData: SignedData(), + id_envelopedData: EnvelopedData(), + id_digestedData: DigestedData(), + id_encryptedData: EncryptedData(), + id_ct_authData: AuthenticatedData(), +} + +cmsContentTypesMap.update(_cmsContentTypesMapUpdate) + + +# CMS Attribute Map + +_cmsAttributesMapUpdate = { + id_contentType: ContentType(), + id_messageDigest: MessageDigest(), + id_signingTime: SigningTime(), + id_countersignature: Countersignature(), +} + +cmsAttributesMap.update(_cmsAttributesMapUpdate) diff --git a/pyasn1_modules/rfc5697.py b/pyasn1_modules/rfc5697.py new file mode 100644 index 0000000..8c5a9d3 --- /dev/null +++ b/pyasn1_modules/rfc5697.py @@ -0,0 +1,70 @@ +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Other Certificates Extension +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5697.txt + +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc4055 + + +# Imports from RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + +CertificateSerialNumber = rfc5280.CertificateSerialNumber + +GeneralNames = rfc5280.GeneralNames + + +# Imports from RFC 4055 + +id_sha1 = rfc4055.id_sha1 + + +# Imports from RFC 5055 +# These are defined here because a module for RFC 5055 does not exist yet + +class SCVPIssuerSerial(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('issuer', GeneralNames()), + namedtype.NamedType('serialNumber', CertificateSerialNumber()) + ) + + +sha1_alg_id = AlgorithmIdentifier() +sha1_alg_id['algorithm'] = id_sha1 + + +class SCVPCertID(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('certHash', univ.OctetString()), + namedtype.NamedType('issuerSerial', SCVPIssuerSerial()), + namedtype.DefaultedNamedType('hashAlgorithm', sha1_alg_id) + ) + + +# Other Certificates Extension + +id_pe_otherCerts = univ.ObjectIdentifier((1, 3, 6, 1, 5, 5, 7, 1, 19,)) + +class OtherCertificates(univ.SequenceOf): + componentType = SCVPCertID() + + +# Update of certificate extension map in rfc5280.py + +_certificateExtensionsMapUpdate = { + id_pe_otherCerts: OtherCertificates(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMapUpdate) diff --git a/pyasn1_modules/rfc5751.py b/pyasn1_modules/rfc5751.py new file mode 100644 index 0000000..7e20001 --- /dev/null +++ b/pyasn1_modules/rfc5751.py @@ -0,0 +1,124 @@ +# This file is being contributed to 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 +# +# S/MIME Version 3.2 Message Specification +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5751.txt + +from pyasn1.type import namedtype +from pyasn1.type import opentype +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc8018 + + +def _OID(*components): + output = [] + for x in tuple(components): + if isinstance(x, univ.ObjectIdentifier): + output.extend(list(x)) + else: + output.append(int(x)) + return univ.ObjectIdentifier(output) + + +# Imports from RFC 5652 and RFC 8018 + +IssuerAndSerialNumber = rfc5652.IssuerAndSerialNumber + +RecipientKeyIdentifier = rfc5652.RecipientKeyIdentifier + +SubjectKeyIdentifier = rfc5652.SubjectKeyIdentifier + +rc2CBC = rfc8018.rc2CBC + + +# S/MIME Capabilities Attribute + +smimeCapabilities = univ.ObjectIdentifier('1.2.840.113549.1.9.15') + + +smimeCapabilityMap = { } + + +class SMIMECapability(univ.Sequence): + pass + +SMIMECapability.componentType = namedtype.NamedTypes( + namedtype.NamedType('capabilityID', univ.ObjectIdentifier()), + namedtype.OptionalNamedType('parameters', univ.Any(), + openType=opentype.OpenType('capabilityID', smimeCapabilityMap)) +) + + +class SMIMECapabilities(univ.SequenceOf): + pass + +SMIMECapabilities.componentType = SMIMECapability() + + +class SMIMECapabilitiesParametersForRC2CBC(univ.Integer): + # which carries the RC2 Key Length (number of bits) + pass + + +# S/MIME Encryption Key Preference Attribute + +id_smime = univ.ObjectIdentifier('1.2.840.113549.1.9.16') + +id_aa = _OID(id_smime, 2) + +id_aa_encrypKeyPref = _OID(id_aa, 11) + + +class SMIMEEncryptionKeyPreference(univ.Choice): + pass + +SMIMEEncryptionKeyPreference.componentType = namedtype.NamedTypes( + namedtype.NamedType('issuerAndSerialNumber', + IssuerAndSerialNumber().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('receipentKeyId', + # Yes, 'receipentKeyId' is spelled incorrectly, but kept + # this way for alignment with the ASN.1 module in the RFC. + RecipientKeyIdentifier().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('subjectAltKeyIdentifier', + SubjectKeyIdentifier().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 2))) +) + + +# The Prefer Binary Inside SMIMECapabilities attribute + +id_cap = _OID(id_smime, 11) + +id_cap_preferBinaryInside = _OID(id_cap, 1) + + +# CMS Attribute Map + +_cmsAttributesMapUpdate = { + smimeCapabilities: SMIMECapabilities(), + id_aa_encrypKeyPref: SMIMEEncryptionKeyPreference(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) + + +# SMIMECapabilities Attribute Map +# +# Do not include OIDs in the dictionary when the parameters are absent. + +_smimeCapabilityMapUpdate = { + rc2CBC: SMIMECapabilitiesParametersForRC2CBC(), +} + +smimeCapabilityMap.update(_smimeCapabilityMapUpdate) diff --git a/pyasn1_modules/rfc5752.py b/pyasn1_modules/rfc5752.py new file mode 100644 index 0000000..1d0df8f --- /dev/null +++ b/pyasn1_modules/rfc5752.py @@ -0,0 +1,49 @@ +# +# 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 +# +# Multiple Signatures in Cryptographic Message Syntax (CMS) +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5752.txt +# https://www.rfc-editor.org/errata/eid4444 +# + +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5035 +from pyasn1_modules import rfc5652 + + +class SignAttrsHash(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('algID', rfc5652.DigestAlgorithmIdentifier()), + namedtype.NamedType('hash', univ.OctetString()) + ) + + +class MultipleSignatures(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('bodyHashAlg', rfc5652.DigestAlgorithmIdentifier()), + namedtype.NamedType('signAlg', rfc5652.SignatureAlgorithmIdentifier()), + namedtype.NamedType('signAttrsHash', SignAttrsHash()), + namedtype.OptionalNamedType('cert', rfc5035.ESSCertIDv2()) + ) + + +id_aa_multipleSignatures = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.51') + + +# Map of Attribute Type OIDs to Attributes added to the +# ones that are in rfc5652.py + +_cmsAttributesMapUpdate = { + id_aa_multipleSignatures: MultipleSignatures(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) diff --git a/pyasn1_modules/rfc5753.py b/pyasn1_modules/rfc5753.py new file mode 100644 index 0000000..94c37c2 --- /dev/null +++ b/pyasn1_modules/rfc5753.py @@ -0,0 +1,157 @@ +# +# 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 +# +# Elliptic Curve Cryptography (ECC) Algorithms in the CMS +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5753.txt +# + +from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful + +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5480 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5751 +from pyasn1_modules import rfc8018 + + +# Imports from RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + + +# Imports from RFC 5652 + +OriginatorPublicKey = rfc5652.OriginatorPublicKey + +UserKeyingMaterial = rfc5652.UserKeyingMaterial + + +# Imports from RFC 5480 + +ECDSA_Sig_Value = rfc5480.ECDSA_Sig_Value + +ECParameters = rfc5480.ECParameters + +ECPoint = rfc5480.ECPoint + +id_ecPublicKey = rfc5480.id_ecPublicKey + + +# Imports from RFC 8018 + +id_hmacWithSHA224 = rfc8018.id_hmacWithSHA224 + +id_hmacWithSHA256 = rfc8018.id_hmacWithSHA256 + +id_hmacWithSHA384 = rfc8018.id_hmacWithSHA384 + +id_hmacWithSHA512 = rfc8018.id_hmacWithSHA512 + + +# Object Identifier arcs + +x9_63_scheme = univ.ObjectIdentifier('1.3.133.16.840.63.0') + +secg_scheme = univ.ObjectIdentifier('1.3.132.1') + + +# Object Identifiers for the algorithms + +dhSinglePass_cofactorDH_sha1kdf_scheme = x9_63_scheme + (3, ) + +dhSinglePass_cofactorDH_sha224kdf_scheme = secg_scheme + (14, 0, ) + +dhSinglePass_cofactorDH_sha256kdf_scheme = secg_scheme + (14, 1, ) + +dhSinglePass_cofactorDH_sha384kdf_scheme = secg_scheme + (14, 2, ) + +dhSinglePass_cofactorDH_sha512kdf_scheme = secg_scheme + (14, 3, ) + +dhSinglePass_stdDH_sha1kdf_scheme = x9_63_scheme + (2, ) + +dhSinglePass_stdDH_sha224kdf_scheme = secg_scheme + (11, 0, ) + +dhSinglePass_stdDH_sha256kdf_scheme = secg_scheme + (11, 1, ) + +dhSinglePass_stdDH_sha384kdf_scheme = secg_scheme + (11, 2, ) + +dhSinglePass_stdDH_sha512kdf_scheme = secg_scheme + (11, 3, ) + +mqvSinglePass_sha1kdf_scheme = x9_63_scheme + (16, ) + +mqvSinglePass_sha224kdf_scheme = secg_scheme + (15, 0, ) + +mqvSinglePass_sha256kdf_scheme = secg_scheme + (15, 1, ) + +mqvSinglePass_sha384kdf_scheme = secg_scheme + (15, 2, ) + +mqvSinglePass_sha512kdf_scheme = secg_scheme + (15, 3, ) + + +# Structures for parameters and key derivation + +class IV(univ.OctetString): + # Exactly 8 octets + pass + + +class CBCParameter(IV): + pass + + +class KeyWrapAlgorithm(AlgorithmIdentifier): + pass + + +class ECC_CMS_SharedInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('keyInfo', KeyWrapAlgorithm()), + namedtype.OptionalNamedType('entityUInfo', + univ.OctetString().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('suppPubInfo', + univ.OctetString().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 2))) + ) + + +class MQVuserKeyingMaterial(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('ephemeralPublicKey', OriginatorPublicKey()), + namedtype.OptionalNamedType('addedukm', + UserKeyingMaterial().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))) + ) + + +# Update the Algorithm Identifier map in rfc5280.py and +# Update the SMIMECapabilities Attribute Map in rfc5751.py + +_algorithmIdentifierMapUpdate = { + dhSinglePass_stdDH_sha1kdf_scheme: KeyWrapAlgorithm(), + dhSinglePass_stdDH_sha224kdf_scheme: KeyWrapAlgorithm(), + dhSinglePass_stdDH_sha256kdf_scheme: KeyWrapAlgorithm(), + dhSinglePass_stdDH_sha384kdf_scheme: KeyWrapAlgorithm(), + dhSinglePass_stdDH_sha512kdf_scheme: KeyWrapAlgorithm(), + dhSinglePass_cofactorDH_sha1kdf_scheme: KeyWrapAlgorithm(), + dhSinglePass_cofactorDH_sha224kdf_scheme: KeyWrapAlgorithm(), + dhSinglePass_cofactorDH_sha256kdf_scheme: KeyWrapAlgorithm(), + dhSinglePass_cofactorDH_sha384kdf_scheme: KeyWrapAlgorithm(), + dhSinglePass_cofactorDH_sha512kdf_scheme: KeyWrapAlgorithm(), + mqvSinglePass_sha1kdf_scheme: KeyWrapAlgorithm(), + mqvSinglePass_sha224kdf_scheme: KeyWrapAlgorithm(), + mqvSinglePass_sha256kdf_scheme: KeyWrapAlgorithm(), + mqvSinglePass_sha384kdf_scheme: KeyWrapAlgorithm(), + mqvSinglePass_sha512kdf_scheme: KeyWrapAlgorithm(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) + +rfc5751.smimeCapabilityMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc5755.py b/pyasn1_modules/rfc5755.py new file mode 100644 index 0000000..14f56fc --- /dev/null +++ b/pyasn1_modules/rfc5755.py @@ -0,0 +1,398 @@ +# +# 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 +# +# An Internet Attribute Certificate Profile for Authorization +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5755.txt +# https://www.rfc-editor.org/rfc/rfc5912.txt (see Section 13) +# + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import opentype +from pyasn1.type import tag +from pyasn1.type import univ +from pyasn1.type import useful + +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 + +MAX = float('inf') + +# Map for Security Category type to value + +securityCategoryMap = { } + + +# Imports from RFC 5652 + +ContentInfo = rfc5652.ContentInfo + + +# Imports from RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + +Attribute = rfc5280.Attribute + +AuthorityInfoAccessSyntax = rfc5280.AuthorityInfoAccessSyntax + +AuthorityKeyIdentifier = rfc5280.AuthorityKeyIdentifier + +CertificateSerialNumber = rfc5280.CertificateSerialNumber + +CRLDistributionPoints = rfc5280.CRLDistributionPoints + +Extensions = rfc5280.Extensions + +Extension = rfc5280.Extension + +GeneralNames = rfc5280.GeneralNames + +GeneralName = rfc5280.GeneralName + +UniqueIdentifier = rfc5280.UniqueIdentifier + + +# Object Identifier arcs + +id_pkix = univ.ObjectIdentifier((1, 3, 6, 1, 5, 5, 7, )) + +id_pe = id_pkix + (1, ) + +id_kp = id_pkix + (3, ) + +id_aca = id_pkix + (10, ) + +id_ad = id_pkix + (48, ) + +id_at = univ.ObjectIdentifier((2, 5, 4, )) + +id_ce = univ.ObjectIdentifier((2, 5, 29, )) + + +# Attribute Certificate + +class AttCertVersion(univ.Integer): + namedValues = namedval.NamedValues( + ('v2', 1) + ) + + +class IssuerSerial(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('issuer', GeneralNames()), + namedtype.NamedType('serial', CertificateSerialNumber()), + namedtype.OptionalNamedType('issuerUID', UniqueIdentifier()) + ) + + +class ObjectDigestInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('digestedObjectType', + univ.Enumerated(namedValues=namedval.NamedValues( + ('publicKey', 0), + ('publicKeyCert', 1), + ('otherObjectTypes', 2)))), + namedtype.OptionalNamedType('otherObjectTypeID', + univ.ObjectIdentifier()), + namedtype.NamedType('digestAlgorithm', + AlgorithmIdentifier()), + namedtype.NamedType('objectDigest', + univ.BitString()) + ) + + +class Holder(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('baseCertificateID', + IssuerSerial().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.OptionalNamedType('entityName', + GeneralNames().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('objectDigestInfo', + ObjectDigestInfo().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 2))) +) + + +class V2Form(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('issuerName', + GeneralNames()), + namedtype.OptionalNamedType('baseCertificateID', + IssuerSerial().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.OptionalNamedType('objectDigestInfo', + ObjectDigestInfo().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 1))) + ) + + +class AttCertIssuer(univ.Choice): + componentType = namedtype.NamedTypes( + namedtype.NamedType('v1Form', GeneralNames()), + namedtype.NamedType('v2Form', V2Form().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 0))) + ) + + +class AttCertValidityPeriod(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('notBeforeTime', useful.GeneralizedTime()), + namedtype.NamedType('notAfterTime', useful.GeneralizedTime()) + ) + + +class AttributeCertificateInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('version', + AttCertVersion()), + namedtype.NamedType('holder', + Holder()), + namedtype.NamedType('issuer', + AttCertIssuer()), + namedtype.NamedType('signature', + AlgorithmIdentifier()), + namedtype.NamedType('serialNumber', + CertificateSerialNumber()), + namedtype.NamedType('attrCertValidityPeriod', + AttCertValidityPeriod()), + namedtype.NamedType('attributes', + univ.SequenceOf(componentType=Attribute())), + namedtype.OptionalNamedType('issuerUniqueID', + UniqueIdentifier()), + namedtype.OptionalNamedType('extensions', + Extensions()) + ) + + +class AttributeCertificate(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('acinfo', AttributeCertificateInfo()), + namedtype.NamedType('signatureAlgorithm', AlgorithmIdentifier()), + namedtype.NamedType('signatureValue', univ.BitString()) + ) + + +# Attribute Certificate Extensions + +id_pe_ac_auditIdentity = id_pe + (4, ) + +id_ce_noRevAvail = id_ce + (56, ) + +id_ce_targetInformation = id_ce + (55, ) + + +class TargetCert(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('targetCertificate', IssuerSerial()), + namedtype.OptionalNamedType('targetName', GeneralName()), + namedtype.OptionalNamedType('certDigestInfo', ObjectDigestInfo()) + ) + + +class Target(univ.Choice): + componentType = namedtype.NamedTypes( + namedtype.NamedType('targetName', + GeneralName().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('targetGroup', + GeneralName().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('targetCert', + TargetCert().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 2))) + ) + + +class Targets(univ.SequenceOf): + componentType = Target() + + +id_pe_ac_proxying = id_pe + (10, ) + + +class ProxyInfo(univ.SequenceOf): + componentType = Targets() + + +id_pe_aaControls = id_pe + (6, ) + + +class AttrSpec(univ.SequenceOf): + componentType = univ.ObjectIdentifier() + + +class AAControls(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('pathLenConstraint', + univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(0, MAX))), + namedtype.OptionalNamedType('permittedAttrs', + AttrSpec().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('excludedAttrs', + AttrSpec().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.DefaultedNamedType('permitUnSpecified', + univ.Boolean().subtype(value=1)) + ) + + +# Attribute Certificate Attributes + +id_aca_authenticationInfo = id_aca + (1, ) + + +id_aca_accessIdentity = id_aca + (2, ) + + +class SvceAuthInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('service', GeneralName()), + namedtype.NamedType('ident', GeneralName()), + namedtype.OptionalNamedType('authInfo', univ.OctetString()) + ) + + +id_aca_chargingIdentity = id_aca + (3, ) + + +id_aca_group = id_aca + (4, ) + + +class IetfAttrSyntax(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('policyAuthority', + GeneralNames().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('values', univ.SequenceOf( + componentType=univ.Choice(componentType=namedtype.NamedTypes( + namedtype.NamedType('octets', univ.OctetString()), + namedtype.NamedType('oid', univ.ObjectIdentifier()), + namedtype.NamedType('string', char.UTF8String()) + )) + )) + ) + + +id_at_role = id_at + (72,) + + +class RoleSyntax(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('roleAuthority', + GeneralNames().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('roleName', + GeneralName().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))) + ) + + +class ClassList(univ.BitString): + namedValues = namedval.NamedValues( + ('unmarked', 0), + ('unclassified', 1), + ('restricted', 2), + ('confidential', 3), + ('secret', 4), + ('topSecret', 5) + ) + + +class SecurityCategory(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('type', + univ.ObjectIdentifier().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('value', + univ.Any().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1)), + openType=opentype.OpenType('type', securityCategoryMap)) + ) + + +id_at_clearance = univ.ObjectIdentifier((2, 5, 4, 55, )) + + +class Clearance(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('policyId', + univ.ObjectIdentifier()), + namedtype.DefaultedNamedType('classList', + ClassList().subtype(value='unclassified')), + namedtype.OptionalNamedType('securityCategories', + univ.SetOf(componentType=SecurityCategory())) + ) + + +id_at_clearance_rfc3281 = univ.ObjectIdentifier((2, 5, 1, 5, 55, )) + + +class Clearance_rfc3281(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('policyId', + univ.ObjectIdentifier().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.DefaultedNamedType('classList', + ClassList().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1)).subtype( + value='unclassified')), + namedtype.OptionalNamedType('securityCategories', + univ.SetOf(componentType=SecurityCategory()).subtype( + implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 2))) + ) + + +id_aca_encAttrs = id_aca + (6, ) + + +class ACClearAttrs(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('acIssuer', GeneralName()), + namedtype.NamedType('acSerial', univ.Integer()), + namedtype.NamedType('attrs', univ.SequenceOf(componentType=Attribute())) + ) + + +# Map of Certificate Extension OIDs to Extensions added to the +# ones that are in rfc5280.py + +_certificateExtensionsMapUpdate = { + id_pe_ac_auditIdentity: univ.OctetString(), + id_ce_noRevAvail: univ.Null(), + id_ce_targetInformation: Targets(), + id_pe_ac_proxying: ProxyInfo(), + id_pe_aaControls: AAControls(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMapUpdate) + + +# Map of AttributeType OIDs to AttributeValue added to the +# ones that are in rfc5280.py + +_certificateAttributesMapUpdate = { + id_aca_authenticationInfo: SvceAuthInfo(), + id_aca_accessIdentity: SvceAuthInfo(), + id_aca_chargingIdentity: IetfAttrSyntax(), + id_aca_group: IetfAttrSyntax(), + id_at_role: RoleSyntax(), + id_at_clearance: Clearance(), + id_at_clearance_rfc3281: Clearance_rfc3281(), + id_aca_encAttrs: ContentInfo(), +} + +rfc5280.certificateAttributesMap.update(_certificateAttributesMapUpdate) diff --git a/pyasn1_modules/rfc5913.py b/pyasn1_modules/rfc5913.py new file mode 100644 index 0000000..0bd0653 --- /dev/null +++ b/pyasn1_modules/rfc5913.py @@ -0,0 +1,44 @@ +# +# 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 +# +# Authority Clearance Constraints Certificate Extension +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5913.txt +# https://www.rfc-editor.org/errata/eid5890 +# + +from pyasn1.type import constraint +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5755 + +MAX = float('inf') + + +# Authority Clearance Constraints Certificate Extension + +id_pe_clearanceConstraints = univ.ObjectIdentifier('1.3.6.1.5.5.7.1.21') + +id_pe_authorityClearanceConstraints = id_pe_clearanceConstraints + + +class AuthorityClearanceConstraints(univ.SequenceOf): + componentType = rfc5755.Clearance() + subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + + +# Map of Certificate Extension OIDs to Extensions added to the +# ones that are in rfc5280.py + +_certificateExtensionsMapUpdate = { + id_pe_clearanceConstraints: AuthorityClearanceConstraints(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMapUpdate) diff --git a/pyasn1_modules/rfc5914.py b/pyasn1_modules/rfc5914.py new file mode 100644 index 0000000..d125ea2 --- /dev/null +++ b/pyasn1_modules/rfc5914.py @@ -0,0 +1,119 @@ +# This file is being contributed to 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 +# +# Trust Anchor Format +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5914.txt + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +MAX = float('inf') + +Certificate = rfc5280.Certificate + +Name = rfc5280.Name + +Extensions = rfc5280.Extensions + +SubjectPublicKeyInfo = rfc5280.SubjectPublicKeyInfo + +TBSCertificate = rfc5280.TBSCertificate + +CertificatePolicies = rfc5280.CertificatePolicies + +KeyIdentifier = rfc5280.KeyIdentifier + +NameConstraints = rfc5280.NameConstraints + + +class CertPolicyFlags(univ.BitString): + pass + +CertPolicyFlags.namedValues = namedval.NamedValues( + ('inhibitPolicyMapping', 0), + ('requireExplicitPolicy', 1), + ('inhibitAnyPolicy', 2) +) + + +class CertPathControls(univ.Sequence): + pass + +CertPathControls.componentType = namedtype.NamedTypes( + namedtype.NamedType('taName', Name()), + namedtype.OptionalNamedType('certificate', Certificate().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('policySet', CertificatePolicies().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('policyFlags', CertPolicyFlags().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.OptionalNamedType('nameConstr', NameConstraints().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.OptionalNamedType('pathLenConstraint', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(0, MAX)).subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))) +) + + +class TrustAnchorTitle(char.UTF8String): + pass + +TrustAnchorTitle.subtypeSpec = constraint.ValueSizeConstraint(1, 64) + + +class TrustAnchorInfoVersion(univ.Integer): + pass + +TrustAnchorInfoVersion.namedValues = namedval.NamedValues( + ('v1', 1) +) + + +class TrustAnchorInfo(univ.Sequence): + pass + +TrustAnchorInfo.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', TrustAnchorInfoVersion().subtype(value='v1')), + namedtype.NamedType('pubKey', SubjectPublicKeyInfo()), + namedtype.NamedType('keyId', KeyIdentifier()), + namedtype.OptionalNamedType('taTitle', TrustAnchorTitle()), + namedtype.OptionalNamedType('certPath', CertPathControls()), + namedtype.OptionalNamedType('exts', Extensions().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('taTitleLangTag', char.UTF8String().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) +) + + +class TrustAnchorChoice(univ.Choice): + pass + +TrustAnchorChoice.componentType = namedtype.NamedTypes( + namedtype.NamedType('certificate', Certificate()), + namedtype.NamedType('tbsCert', TBSCertificate().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('taInfo', TrustAnchorInfo().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))) +) + + +id_ct_trustAnchorList = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.34') + +class TrustAnchorList(univ.SequenceOf): + pass + +TrustAnchorList.componentType = TrustAnchorChoice() +TrustAnchorList.subtypeSpec=constraint.ValueSizeConstraint(1, MAX) diff --git a/pyasn1_modules/rfc5915.py b/pyasn1_modules/rfc5915.py new file mode 100644 index 0000000..82ff4a3 --- /dev/null +++ b/pyasn1_modules/rfc5915.py @@ -0,0 +1,32 @@ +# This file is being contributed to 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 +# +# Elliptic Curve Private Key +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5915.txt + +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5480 + + +class ECPrivateKey(univ.Sequence): + pass + +ECPrivateKey.componentType = namedtype.NamedTypes( + namedtype.NamedType('version', univ.Integer( + namedValues=namedval.NamedValues(('ecPrivkeyVer1', 1)))), + namedtype.NamedType('privateKey', univ.OctetString()), + namedtype.OptionalNamedType('parameters', rfc5480.ECParameters().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('publicKey', univ.BitString().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) diff --git a/pyasn1_modules/rfc5916.py b/pyasn1_modules/rfc5916.py new file mode 100644 index 0000000..ac23c86 --- /dev/null +++ b/pyasn1_modules/rfc5916.py @@ -0,0 +1,35 @@ +# +# 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 +# +# Device Owner Attribute +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5916.txt +# + +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +# Device Owner Attribute + +id_deviceOwner = univ.ObjectIdentifier((2, 16, 840, 1, 101, 2, 1, 5, 69)) + +at_deviceOwner = rfc5280.Attribute() +at_deviceOwner['type'] = id_deviceOwner +at_deviceOwner['values'][0] = univ.ObjectIdentifier() + + +# Add to the map of Attribute Type OIDs to Attributes in rfc5280.py. + +_certificateAttributesMapUpdate = { + id_deviceOwner: univ.ObjectIdentifier(), +} + +rfc5280.certificateAttributesMap.update(_certificateAttributesMapUpdate) diff --git a/pyasn1_modules/rfc5917.py b/pyasn1_modules/rfc5917.py new file mode 100644 index 0000000..ed9af98 --- /dev/null +++ b/pyasn1_modules/rfc5917.py @@ -0,0 +1,55 @@ +# +# 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 +# +# Clearance Sponsor Attribute +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5917.txt +# https://www.rfc-editor.org/errata/eid4558 +# https://www.rfc-editor.org/errata/eid5883 +# + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +# DirectoryString is the same as RFC 5280, except for two things: +# 1. the length is limited to 64; +# 2. only the 'utf8String' choice remains because the ASN.1 +# specification says: ( WITH COMPONENTS { utf8String PRESENT } ) + +class DirectoryString(univ.Choice): + componentType = namedtype.NamedTypes( + namedtype.NamedType('utf8String', char.UTF8String().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, 64))), + ) + + +# Clearance Sponsor Attribute + +id_clearanceSponsor = univ.ObjectIdentifier((2, 16, 840, 1, 101, 2, 1, 5, 68)) + +ub_clearance_sponsor = univ.Integer(64) + + +at_clearanceSponsor = rfc5280.Attribute() +at_clearanceSponsor['type'] = id_clearanceSponsor +at_clearanceSponsor['values'][0] = DirectoryString() + + +# Add to the map of Attribute Type OIDs to Attributes in rfc5280.py. + +_certificateAttributesMapUpdate = { + id_clearanceSponsor: DirectoryString(), +} + +rfc5280.certificateAttributesMap.update(_certificateAttributesMapUpdate) diff --git a/pyasn1_modules/rfc5924.py b/pyasn1_modules/rfc5924.py new file mode 100644 index 0000000..4358e4f --- /dev/null +++ b/pyasn1_modules/rfc5924.py @@ -0,0 +1,19 @@ +# +# 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 +# +# Extended Key Usage (EKU) for Session Initiation Protocol (SIP) +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5924.txt +# + +from pyasn1.type import univ + +id_kp = univ.ObjectIdentifier('1.3.6.1.5.5.7.3') + +id_kp_sipDomain = id_kp + (20, ) diff --git a/pyasn1_modules/rfc5934.py b/pyasn1_modules/rfc5934.py new file mode 100644 index 0000000..e3ad247 --- /dev/null +++ b/pyasn1_modules/rfc5934.py @@ -0,0 +1,786 @@ +# This file is being contributed to 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 +# +# Trust Anchor Format +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5934.txt + +from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful + +from pyasn1_modules import rfc2985 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5914 + +MAX = float('inf') + + +def _OID(*components): + output = [] + for x in tuple(components): + if isinstance(x, univ.ObjectIdentifier): + output.extend(list(x)) + else: + output.append(int(x)) + return univ.ObjectIdentifier(output) + + +# Imports from RFC 2985 + +SingleAttribute = rfc2985.SingleAttribute + + +# Imports from RFC5914 + +CertPathControls = rfc5914.CertPathControls + +TrustAnchorChoice = rfc5914.TrustAnchorChoice + +TrustAnchorTitle = rfc5914.TrustAnchorTitle + + +# Imports from RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + +AnotherName = rfc5280.AnotherName + +Attribute = rfc5280.Attribute + +Certificate = rfc5280.Certificate + +CertificateSerialNumber = rfc5280.CertificateSerialNumber + +Extension = rfc5280.Extension + +Extensions = rfc5280.Extensions + +KeyIdentifier = rfc5280.KeyIdentifier + +Name = rfc5280.Name + +SubjectPublicKeyInfo = rfc5280.SubjectPublicKeyInfo + +TBSCertificate = rfc5280.TBSCertificate + +Validity = rfc5280.Validity + + +# Object Identifier Arc for TAMP Message Content Types + +id_tamp = univ.ObjectIdentifier('2.16.840.1.101.2.1.2.77') + + +# TAMP Status Query Message + +id_ct_TAMP_statusQuery = _OID(id_tamp, 1) + + +class TAMPVersion(univ.Integer): + pass + +TAMPVersion.namedValues = namedval.NamedValues( + ('v1', 1), + ('v2', 2) +) + + +class TerseOrVerbose(univ.Enumerated): + pass + +TerseOrVerbose.namedValues = namedval.NamedValues( + ('terse', 1), + ('verbose', 2) +) + + +class HardwareSerialEntry(univ.Choice): + pass + +HardwareSerialEntry.componentType = namedtype.NamedTypes( + namedtype.NamedType('all', univ.Null()), + namedtype.NamedType('single', univ.OctetString()), + namedtype.NamedType('block', univ.Sequence(componentType=namedtype.NamedTypes( + namedtype.NamedType('low', univ.OctetString()), + namedtype.NamedType('high', univ.OctetString()) + )) + ) +) + + +class HardwareModules(univ.Sequence): + pass + +HardwareModules.componentType = namedtype.NamedTypes( + namedtype.NamedType('hwType', univ.ObjectIdentifier()), + namedtype.NamedType('hwSerialEntries', univ.SequenceOf( + componentType=HardwareSerialEntry()).subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, MAX))) +) + + +class HardwareModuleIdentifierList(univ.SequenceOf): + pass + +HardwareModuleIdentifierList.componentType = HardwareModules() +HardwareModuleIdentifierList.subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + + +class Community(univ.ObjectIdentifier): + pass + + +class CommunityIdentifierList(univ.SequenceOf): + pass + +CommunityIdentifierList.componentType = Community() +CommunityIdentifierList.subtypeSpec=constraint.ValueSizeConstraint(0, MAX) + + +class TargetIdentifier(univ.Choice): + pass + +TargetIdentifier.componentType = namedtype.NamedTypes( + namedtype.NamedType('hwModules', HardwareModuleIdentifierList().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('communities', CommunityIdentifierList().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.NamedType('allModules', univ.Null().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.NamedType('uri', char.IA5String().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))), + namedtype.NamedType('otherName', AnotherName().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 5))) +) + + +class SeqNumber(univ.Integer): + pass + +SeqNumber.subtypeSpec = constraint.ValueRangeConstraint(0, 9223372036854775807) + + +class TAMPMsgRef(univ.Sequence): + pass + +TAMPMsgRef.componentType = namedtype.NamedTypes( + namedtype.NamedType('target', TargetIdentifier()), + namedtype.NamedType('seqNum', SeqNumber()) +) + + +class TAMPStatusQuery(univ.Sequence): + pass + +TAMPStatusQuery.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', TAMPVersion().subtype( + implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0)).subtype(value='v2')), + namedtype.DefaultedNamedType('terse', TerseOrVerbose().subtype( + implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 1)).subtype(value='verbose')), + namedtype.NamedType('query', TAMPMsgRef()) +) + + +tamp_status_query = rfc5652.ContentInfo() +tamp_status_query['contentType'] = id_ct_TAMP_statusQuery +tamp_status_query['content'] = TAMPStatusQuery() + + +# TAMP Status Response Message + +id_ct_TAMP_statusResponse = _OID(id_tamp, 2) + + +class KeyIdentifiers(univ.SequenceOf): + pass + +KeyIdentifiers.componentType = KeyIdentifier() +KeyIdentifiers.subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + + +class TrustAnchorChoiceList(univ.SequenceOf): + pass + +TrustAnchorChoiceList.componentType = TrustAnchorChoice() +TrustAnchorChoiceList.subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + + +class TAMPSequenceNumber(univ.Sequence): + pass + +TAMPSequenceNumber.componentType = namedtype.NamedTypes( + namedtype.NamedType('keyId', KeyIdentifier()), + namedtype.NamedType('seqNumber', SeqNumber()) +) + + +class TAMPSequenceNumbers(univ.SequenceOf): + pass + +TAMPSequenceNumbers.componentType = TAMPSequenceNumber() +TAMPSequenceNumbers.subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + + +class TerseStatusResponse(univ.Sequence): + pass + +TerseStatusResponse.componentType = namedtype.NamedTypes( + namedtype.NamedType('taKeyIds', KeyIdentifiers()), + namedtype.OptionalNamedType('communities', CommunityIdentifierList()) +) + + +class VerboseStatusResponse(univ.Sequence): + pass + +VerboseStatusResponse.componentType = namedtype.NamedTypes( + namedtype.NamedType('taInfo', TrustAnchorChoiceList()), + namedtype.OptionalNamedType('continPubKeyDecryptAlg', + AlgorithmIdentifier().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('communities', + CommunityIdentifierList().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('tampSeqNumbers', + TAMPSequenceNumbers().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 2))) +) + + +class StatusResponse(univ.Choice): + pass + +StatusResponse.componentType = namedtype.NamedTypes( + namedtype.NamedType('terseResponse', TerseStatusResponse().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.NamedType('verboseResponse', VerboseStatusResponse().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))) +) + + +class TAMPStatusResponse(univ.Sequence): + pass + +TAMPStatusResponse.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', TAMPVersion().subtype( + implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0)).subtype(value='v2')), + namedtype.NamedType('query', TAMPMsgRef()), + namedtype.NamedType('response', StatusResponse()), + namedtype.DefaultedNamedType('usesApex', univ.Boolean().subtype(value=1)) +) + + +tamp_status_response = rfc5652.ContentInfo() +tamp_status_response['contentType'] = id_ct_TAMP_statusResponse +tamp_status_response['content'] = TAMPStatusResponse() + + +# Trust Anchor Update Message + +id_ct_TAMP_update = _OID(id_tamp, 3) + + +class TBSCertificateChangeInfo(univ.Sequence): + pass + +TBSCertificateChangeInfo.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('serialNumber', CertificateSerialNumber()), + namedtype.OptionalNamedType('signature', AlgorithmIdentifier().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('issuer', Name().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('validity', Validity().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.OptionalNamedType('subject', Name().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.NamedType('subjectPublicKeyInfo', SubjectPublicKeyInfo().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))), + namedtype.OptionalNamedType('exts', Extensions().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 5))) +) + + +class TrustAnchorChangeInfo(univ.Sequence): + pass + +TrustAnchorChangeInfo.componentType = namedtype.NamedTypes( + namedtype.NamedType('pubKey', SubjectPublicKeyInfo()), + namedtype.OptionalNamedType('keyId', KeyIdentifier()), + namedtype.OptionalNamedType('taTitle', TrustAnchorTitle()), + namedtype.OptionalNamedType('certPath', CertPathControls()), + namedtype.OptionalNamedType('exts', Extensions().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class TrustAnchorChangeInfoChoice(univ.Choice): + pass + +TrustAnchorChangeInfoChoice.componentType = namedtype.NamedTypes( + namedtype.NamedType('tbsCertChange', TBSCertificateChangeInfo().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.NamedType('taChange', TrustAnchorChangeInfo().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))) +) + + +class TrustAnchorUpdate(univ.Choice): + pass + +TrustAnchorUpdate.componentType = namedtype.NamedTypes( + namedtype.NamedType('add', TrustAnchorChoice().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('remove', SubjectPublicKeyInfo().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.NamedType('change', TrustAnchorChangeInfoChoice().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))) +) + + +class TAMPUpdate(univ.Sequence): + pass + +TAMPUpdate.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', + TAMPVersion().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0)).subtype(value='v2')), + namedtype.DefaultedNamedType('terse', + TerseOrVerbose().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 1)).subtype(value='verbose')), + namedtype.NamedType('msgRef', TAMPMsgRef()), + namedtype.NamedType('updates', + univ.SequenceOf(componentType=TrustAnchorUpdate()).subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, MAX))), + namedtype.OptionalNamedType('tampSeqNumbers', + TAMPSequenceNumbers().subtype(implicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 2))) +) + + +tamp_update = rfc5652.ContentInfo() +tamp_update['contentType'] = id_ct_TAMP_update +tamp_update['content'] = TAMPUpdate() + + +# Trust Anchor Update Confirm Message + +id_ct_TAMP_updateConfirm = _OID(id_tamp, 4) + + +class StatusCode(univ.Enumerated): + pass + +StatusCode.namedValues = namedval.NamedValues( + ('success', 0), + ('decodeFailure', 1), + ('badContentInfo', 2), + ('badSignedData', 3), + ('badEncapContent', 4), + ('badCertificate', 5), + ('badSignerInfo', 6), + ('badSignedAttrs', 7), + ('badUnsignedAttrs', 8), + ('missingContent', 9), + ('noTrustAnchor', 10), + ('notAuthorized', 11), + ('badDigestAlgorithm', 12), + ('badSignatureAlgorithm', 13), + ('unsupportedKeySize', 14), + ('unsupportedParameters', 15), + ('signatureFailure', 16), + ('insufficientMemory', 17), + ('unsupportedTAMPMsgType', 18), + ('apexTAMPAnchor', 19), + ('improperTAAddition', 20), + ('seqNumFailure', 21), + ('contingencyPublicKeyDecrypt', 22), + ('incorrectTarget', 23), + ('communityUpdateFailed', 24), + ('trustAnchorNotFound', 25), + ('unsupportedTAAlgorithm', 26), + ('unsupportedTAKeySize', 27), + ('unsupportedContinPubKeyDecryptAlg', 28), + ('missingSignature', 29), + ('resourcesBusy', 30), + ('versionNumberMismatch', 31), + ('missingPolicySet', 32), + ('revokedCertificate', 33), + ('unsupportedTrustAnchorFormat', 34), + ('improperTAChange', 35), + ('malformed', 36), + ('cmsError', 37), + ('unsupportedTargetIdentifier', 38), + ('other', 127) +) + + +class StatusCodeList(univ.SequenceOf): + pass + +StatusCodeList.componentType = StatusCode() +StatusCodeList.subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + + +class TerseUpdateConfirm(StatusCodeList): + pass + + +class VerboseUpdateConfirm(univ.Sequence): + pass + +VerboseUpdateConfirm.componentType = namedtype.NamedTypes( + namedtype.NamedType('status', StatusCodeList()), + namedtype.NamedType('taInfo', TrustAnchorChoiceList()), + namedtype.OptionalNamedType('tampSeqNumbers', TAMPSequenceNumbers()), + namedtype.DefaultedNamedType('usesApex', univ.Boolean().subtype(value=1)) +) + + +class UpdateConfirm(univ.Choice): + pass + +UpdateConfirm.componentType = namedtype.NamedTypes( + namedtype.NamedType('terseConfirm', TerseUpdateConfirm().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('verboseConfirm', VerboseUpdateConfirm().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))) +) + + +class TAMPUpdateConfirm(univ.Sequence): + pass + +TAMPUpdateConfirm.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', TAMPVersion().subtype( + implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0)).subtype(value='v2')), + namedtype.NamedType('update', TAMPMsgRef()), + namedtype.NamedType('confirm', UpdateConfirm()) +) + + +tamp_update_confirm = rfc5652.ContentInfo() +tamp_update_confirm['contentType'] = id_ct_TAMP_updateConfirm +tamp_update_confirm['content'] = TAMPUpdateConfirm() + + +# Apex Trust Anchor Update Message + +id_ct_TAMP_apexUpdate = _OID(id_tamp, 5) + + +class TAMPApexUpdate(univ.Sequence): + pass + +TAMPApexUpdate.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', + TAMPVersion().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0)).subtype(value='v2')), + namedtype.DefaultedNamedType('terse', + TerseOrVerbose().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 1)).subtype(value='verbose')), + namedtype.NamedType('msgRef', TAMPMsgRef()), + namedtype.NamedType('clearTrustAnchors', univ.Boolean()), + namedtype.NamedType('clearCommunities', univ.Boolean()), + namedtype.OptionalNamedType('seqNumber', SeqNumber()), + namedtype.NamedType('apexTA', TrustAnchorChoice()) +) + + +tamp_apex_update = rfc5652.ContentInfo() +tamp_apex_update['contentType'] = id_ct_TAMP_apexUpdate +tamp_apex_update['content'] = TAMPApexUpdate() + + +# Apex Trust Anchor Update Confirm Message + +id_ct_TAMP_apexUpdateConfirm = _OID(id_tamp, 6) + + +class TerseApexUpdateConfirm(StatusCode): + pass + + +class VerboseApexUpdateConfirm(univ.Sequence): + pass + +VerboseApexUpdateConfirm.componentType = namedtype.NamedTypes( + namedtype.NamedType('status', StatusCode()), + namedtype.NamedType('taInfo', TrustAnchorChoiceList()), + namedtype.OptionalNamedType('communities', + CommunityIdentifierList().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('tampSeqNumbers', + TAMPSequenceNumbers().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 1))) +) + + +class ApexUpdateConfirm(univ.Choice): + pass + +ApexUpdateConfirm.componentType = namedtype.NamedTypes( + namedtype.NamedType('terseApexConfirm', + TerseApexUpdateConfirm().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0))), + namedtype.NamedType('verboseApexConfirm', + VerboseApexUpdateConfirm().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatConstructed, 1))) +) + + +class TAMPApexUpdateConfirm(univ.Sequence): + pass + +TAMPApexUpdateConfirm.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', + TAMPVersion().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0)).subtype(value='v2')), + namedtype.NamedType('apexReplace', TAMPMsgRef()), + namedtype.NamedType('apexConfirm', ApexUpdateConfirm()) +) + + +tamp_apex_update_confirm = rfc5652.ContentInfo() +tamp_apex_update_confirm['contentType'] = id_ct_TAMP_apexUpdateConfirm +tamp_apex_update_confirm['content'] = TAMPApexUpdateConfirm() + + +# Community Update Message + +id_ct_TAMP_communityUpdate = _OID(id_tamp, 7) + + +class CommunityUpdates(univ.Sequence): + pass + +CommunityUpdates.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('remove', + CommunityIdentifierList().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('add', + CommunityIdentifierList().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 2))) +) + + +class TAMPCommunityUpdate(univ.Sequence): + pass + +TAMPCommunityUpdate.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', + TAMPVersion().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0)).subtype(value='v2')), + namedtype.DefaultedNamedType('terse', + TerseOrVerbose().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 1)).subtype(value='verbose')), + namedtype.NamedType('msgRef', TAMPMsgRef()), + namedtype.NamedType('updates', CommunityUpdates()) +) + + +tamp_community_update = rfc5652.ContentInfo() +tamp_community_update['contentType'] = id_ct_TAMP_communityUpdate +tamp_community_update['content'] = TAMPCommunityUpdate() + + +# Community Update Confirm Message + +id_ct_TAMP_communityUpdateConfirm = _OID(id_tamp, 8) + + +class TerseCommunityConfirm(StatusCode): + pass + + +class VerboseCommunityConfirm(univ.Sequence): + pass + +VerboseCommunityConfirm.componentType = namedtype.NamedTypes( + namedtype.NamedType('status', StatusCode()), + namedtype.OptionalNamedType('communities', CommunityIdentifierList()) +) + + +class CommunityConfirm(univ.Choice): + pass + +CommunityConfirm.componentType = namedtype.NamedTypes( + namedtype.NamedType('terseCommConfirm', + TerseCommunityConfirm().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0))), + namedtype.NamedType('verboseCommConfirm', + VerboseCommunityConfirm().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatConstructed, 1))) +) + + +class TAMPCommunityUpdateConfirm(univ.Sequence): + pass + +TAMPCommunityUpdateConfirm.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', + TAMPVersion().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0)).subtype(value='v2')), + namedtype.NamedType('update', TAMPMsgRef()), + namedtype.NamedType('commConfirm', CommunityConfirm()) +) + + +tamp_community_update_confirm = rfc5652.ContentInfo() +tamp_community_update_confirm['contentType'] = id_ct_TAMP_communityUpdateConfirm +tamp_community_update_confirm['content'] = TAMPCommunityUpdateConfirm() + + +# Sequence Number Adjust Message + +id_ct_TAMP_seqNumAdjust = _OID(id_tamp, 10) + + + +class SequenceNumberAdjust(univ.Sequence): + pass + +SequenceNumberAdjust.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', + TAMPVersion().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0)).subtype(value='v2')), + namedtype.NamedType('msgRef', TAMPMsgRef()) +) + + +tamp_sequence_number_adjust = rfc5652.ContentInfo() +tamp_sequence_number_adjust['contentType'] = id_ct_TAMP_seqNumAdjust +tamp_sequence_number_adjust['content'] = SequenceNumberAdjust() + + +# Sequence Number Adjust Confirm Message + +id_ct_TAMP_seqNumAdjustConfirm = _OID(id_tamp, 11) + + +class SequenceNumberAdjustConfirm(univ.Sequence): + pass + +SequenceNumberAdjustConfirm.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', + TAMPVersion().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0)).subtype(value='v2')), + namedtype.NamedType('adjust', TAMPMsgRef()), + namedtype.NamedType('status', StatusCode()) +) + + +tamp_sequence_number_adjust_confirm = rfc5652.ContentInfo() +tamp_sequence_number_adjust_confirm['contentType'] = id_ct_TAMP_seqNumAdjustConfirm +tamp_sequence_number_adjust_confirm['content'] = SequenceNumberAdjustConfirm() + + +# TAMP Error Message + +id_ct_TAMP_error = _OID(id_tamp, 9) + + +class TAMPError(univ.Sequence): + pass + +TAMPError.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', + TAMPVersion().subtype(implicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0)).subtype(value='v2')), + namedtype.NamedType('msgType', univ.ObjectIdentifier()), + namedtype.NamedType('status', StatusCode()), + namedtype.OptionalNamedType('msgRef', TAMPMsgRef()) +) + + +tamp_error = rfc5652.ContentInfo() +tamp_error['contentType'] = id_ct_TAMP_error +tamp_error['content'] = TAMPError() + + +# Object Identifier Arc for Attributes + +id_attributes = univ.ObjectIdentifier('2.16.840.1.101.2.1.5') + + +# contingency-public-key-decrypt-key unsigned attribute + +id_aa_TAMP_contingencyPublicKeyDecryptKey = _OID(id_attributes, 63) + + +class PlaintextSymmetricKey(univ.OctetString): + pass + + +contingency_public_key_decrypt_key = Attribute() +contingency_public_key_decrypt_key['type'] = id_aa_TAMP_contingencyPublicKeyDecryptKey +contingency_public_key_decrypt_key['values'][0] = PlaintextSymmetricKey() + + +# id-pe-wrappedApexContinKey extension + +id_pe_wrappedApexContinKey =univ.ObjectIdentifier('1.3.6.1.5.5.7.1.20') + + +class ApexContingencyKey(univ.Sequence): + pass + +ApexContingencyKey.componentType = namedtype.NamedTypes( + namedtype.NamedType('wrapAlgorithm', AlgorithmIdentifier()), + namedtype.NamedType('wrappedContinPubKey', univ.OctetString()) +) + + +wrappedApexContinKey = Extension() +wrappedApexContinKey['extnID'] = id_pe_wrappedApexContinKey +wrappedApexContinKey['critical'] = 0 +wrappedApexContinKey['extnValue'] = univ.OctetString() + + +# Add to the map of CMS Content Type OIDs to Content Types in +# rfc5652.py + +_cmsContentTypesMapUpdate = { + id_ct_TAMP_statusQuery: TAMPStatusQuery(), + id_ct_TAMP_statusResponse: TAMPStatusResponse(), + id_ct_TAMP_update: TAMPUpdate(), + id_ct_TAMP_updateConfirm: TAMPUpdateConfirm(), + id_ct_TAMP_apexUpdate: TAMPApexUpdate(), + id_ct_TAMP_apexUpdateConfirm: TAMPApexUpdateConfirm(), + id_ct_TAMP_communityUpdate: TAMPCommunityUpdate(), + id_ct_TAMP_communityUpdateConfirm: TAMPCommunityUpdateConfirm(), + id_ct_TAMP_seqNumAdjust: SequenceNumberAdjust(), + id_ct_TAMP_seqNumAdjustConfirm: SequenceNumberAdjustConfirm(), + id_ct_TAMP_error: TAMPError(), +} + +rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate) + + +# Add to the map of CMS Attribute OIDs to Attribute Values in +# rfc5652.py + +_cmsAttributesMapUpdate = { + id_aa_TAMP_contingencyPublicKeyDecryptKey: PlaintextSymmetricKey(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) + + +# Add to the map of Certificate Extension OIDs to Extensions in +# rfc5280.py + +_certificateExtensionsMap = { + id_pe_wrappedApexContinKey: ApexContingencyKey(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMap) diff --git a/pyasn1_modules/rfc5940.py b/pyasn1_modules/rfc5940.py new file mode 100644 index 0000000..e105923 --- /dev/null +++ b/pyasn1_modules/rfc5940.py @@ -0,0 +1,59 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with assistance from asn1ate v.0.6.0. +# Modified by Russ Housley to add map for use with opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Additional CMS Revocation Information Choices +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5940.txt +# + +from pyasn1.type import namedtype +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc2560 +from pyasn1_modules import rfc5652 + + +# RevocationInfoChoice for OCSP response: +# The OID is included in otherRevInfoFormat, and +# signed OCSPResponse is included in otherRevInfo + +id_ri_ocsp_response = univ.ObjectIdentifier('1.3.6.1.5.5.7.16.2') + +OCSPResponse = rfc2560.OCSPResponse + + +# RevocationInfoChoice for SCVP request/response: +# The OID is included in otherRevInfoFormat, and +# SCVPReqRes is included in otherRevInfo + +id_ri_scvp = univ.ObjectIdentifier('1.3.6.1.5.5.7.16.4') + +ContentInfo = rfc5652.ContentInfo + +class SCVPReqRes(univ.Sequence): + pass + +SCVPReqRes.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('request', + ContentInfo().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('response', ContentInfo()) +) + + +# Map of Revocation Info Format OIDs to Revocation Info Format +# is added to the ones that are in rfc5652.py + +_otherRevInfoFormatMapUpdate = { + id_ri_ocsp_response: OCSPResponse(), + id_ri_scvp: SCVPReqRes(), +} + +rfc5652.otherRevInfoFormatMap.update(_otherRevInfoFormatMapUpdate) diff --git a/pyasn1_modules/rfc5958.py b/pyasn1_modules/rfc5958.py new file mode 100644 index 0000000..1aaa928 --- /dev/null +++ b/pyasn1_modules/rfc5958.py @@ -0,0 +1,98 @@ +# +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley. +# Modified by Russ Housley to add a map for use with opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Asymmetric Key Packages, which is essentially version 2 of +# the PrivateKeyInfo structure in PKCS#8 in RFC 5208 +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5958.txt + +from pyasn1.type import univ, constraint, namedtype, namedval, tag + +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 + + +MAX = float('inf') + + +class KeyEncryptionAlgorithmIdentifier(rfc5280.AlgorithmIdentifier): + pass + + +class PrivateKeyAlgorithmIdentifier(rfc5280.AlgorithmIdentifier): + pass + + +class EncryptedData(univ.OctetString): + pass + + +class EncryptedPrivateKeyInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('encryptionAlgorithm', KeyEncryptionAlgorithmIdentifier()), + namedtype.NamedType('encryptedData', EncryptedData()) + ) + + +class Version(univ.Integer): + namedValues = namedval.NamedValues(('v1', 0), ('v2', 1)) + + +class PrivateKey(univ.OctetString): + pass + + +class Attributes(univ.SetOf): + componentType = rfc5652.Attribute() + + +class PublicKey(univ.BitString): + pass + + +# OneAsymmetricKey is essentially version 2 of PrivateKeyInfo. +# If publicKey is present, then the version must be v2; +# otherwise, the version should be v1. + +class OneAsymmetricKey(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('version', Version()), + namedtype.NamedType('privateKeyAlgorithm', PrivateKeyAlgorithmIdentifier()), + namedtype.NamedType('privateKey', PrivateKey()), + namedtype.OptionalNamedType('attributes', Attributes().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.OptionalNamedType('publicKey', PublicKey().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))) + ) + + +class PrivateKeyInfo(OneAsymmetricKey): + pass + + +# The CMS AsymmetricKeyPackage Content Type + +id_ct_KP_aKeyPackage = univ.ObjectIdentifier('2.16.840.1.101.2.1.2.78.5') + +class AsymmetricKeyPackage(univ.SequenceOf): + pass + +AsymmetricKeyPackage.componentType = OneAsymmetricKey() +AsymmetricKeyPackage.sizeSpec=constraint.ValueSizeConstraint(1, MAX) + + +# Map of Content Type OIDs to Content Types is added to the +# ones that are in rfc5652.py + +_cmsContentTypesMapUpdate = { + id_ct_KP_aKeyPackage: AsymmetricKeyPackage(), +} + +rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate) diff --git a/pyasn1_modules/rfc5990.py b/pyasn1_modules/rfc5990.py new file mode 100644 index 0000000..281316f --- /dev/null +++ b/pyasn1_modules/rfc5990.py @@ -0,0 +1,237 @@ +# +# 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 +# +# Use of the RSA-KEM Key Transport Algorithm in the CMS +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc5990.txt +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + +MAX = float('inf') + +def _OID(*components): + output = [] + for x in tuple(components): + if isinstance(x, univ.ObjectIdentifier): + output.extend(list(x)) + else: + output.append(int(x)) + return univ.ObjectIdentifier(output) + + +# Imports from RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + + +# Useful types and definitions + +class NullParms(univ.Null): + pass + + +# Object identifier arcs + +is18033_2 = _OID(1, 0, 18033, 2) + +nistAlgorithm = _OID(2, 16, 840, 1, 101, 3, 4) + +pkcs_1 = _OID(1, 2, 840, 113549, 1, 1) + +x9_44 = _OID(1, 3, 133, 16, 840, 9, 44) + +x9_44_components = _OID(x9_44, 1) + + +# Types for algorithm identifiers + +class Camellia_KeyWrappingScheme(AlgorithmIdentifier): + pass + +class DataEncapsulationMechanism(AlgorithmIdentifier): + pass + +class KDF2_HashFunction(AlgorithmIdentifier): + pass + +class KDF3_HashFunction(AlgorithmIdentifier): + pass + +class KeyDerivationFunction(AlgorithmIdentifier): + pass + +class KeyEncapsulationMechanism(AlgorithmIdentifier): + pass + +class X9_SymmetricKeyWrappingScheme(AlgorithmIdentifier): + pass + + +# RSA-KEM Key Transport Algorithm + +id_rsa_kem = _OID(1, 2, 840, 113549, 1, 9, 16, 3, 14) + + +class GenericHybridParameters(univ.Sequence): + pass + +GenericHybridParameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('kem', KeyEncapsulationMechanism()), + namedtype.NamedType('dem', DataEncapsulationMechanism()) +) + + +rsa_kem = AlgorithmIdentifier() +rsa_kem['algorithm'] = id_rsa_kem +rsa_kem['parameters'] = GenericHybridParameters() + + +# KEM-RSA Key Encapsulation Mechanism + +id_kem_rsa = _OID(is18033_2, 2, 4) + + +class KeyLength(univ.Integer): + pass + +KeyLength.subtypeSpec = constraint.ValueRangeConstraint(1, MAX) + + +class RsaKemParameters(univ.Sequence): + pass + +RsaKemParameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('keyDerivationFunction', KeyDerivationFunction()), + namedtype.NamedType('keyLength', KeyLength()) +) + + +kem_rsa = AlgorithmIdentifier() +kem_rsa['algorithm'] = id_kem_rsa +kem_rsa['parameters'] = RsaKemParameters() + + +# Key Derivation Functions + +id_kdf_kdf2 = _OID(x9_44_components, 1) + +id_kdf_kdf3 = _OID(x9_44_components, 2) + + +kdf2 = AlgorithmIdentifier() +kdf2['algorithm'] = id_kdf_kdf2 +kdf2['parameters'] = KDF2_HashFunction() + +kdf3 = AlgorithmIdentifier() +kdf3['algorithm'] = id_kdf_kdf3 +kdf3['parameters'] = KDF3_HashFunction() + + +# Hash Functions + +id_sha1 = _OID(1, 3, 14, 3, 2, 26) + +id_sha224 = _OID(2, 16, 840, 1, 101, 3, 4, 2, 4) + +id_sha256 = _OID(2, 16, 840, 1, 101, 3, 4, 2, 1) + +id_sha384 = _OID(2, 16, 840, 1, 101, 3, 4, 2, 2) + +id_sha512 = _OID(2, 16, 840, 1, 101, 3, 4, 2, 3) + + +sha1 = AlgorithmIdentifier() +sha1['algorithm'] = id_sha1 +sha1['parameters'] = univ.Null("") + +sha224 = AlgorithmIdentifier() +sha224['algorithm'] = id_sha224 +sha224['parameters'] = univ.Null("") + +sha256 = AlgorithmIdentifier() +sha256['algorithm'] = id_sha256 +sha256['parameters'] = univ.Null("") + +sha384 = AlgorithmIdentifier() +sha384['algorithm'] = id_sha384 +sha384['parameters'] = univ.Null("") + +sha512 = AlgorithmIdentifier() +sha512['algorithm'] = id_sha512 +sha512['parameters'] = univ.Null("") + + +# Symmetric Key-Wrapping Schemes + +id_aes128_Wrap = _OID(nistAlgorithm, 1, 5) + +id_aes192_Wrap = _OID(nistAlgorithm, 1, 25) + +id_aes256_Wrap = _OID(nistAlgorithm, 1, 45) + +id_alg_CMS3DESwrap = _OID(1, 2, 840, 113549, 1, 9, 16, 3, 6) + +id_camellia128_Wrap = _OID(1, 2, 392, 200011, 61, 1, 1, 3, 2) + +id_camellia192_Wrap = _OID(1, 2, 392, 200011, 61, 1, 1, 3, 3) + +id_camellia256_Wrap = _OID(1, 2, 392, 200011, 61, 1, 1, 3, 4) + + +aes128_Wrap = AlgorithmIdentifier() +aes128_Wrap['algorithm'] = id_aes128_Wrap +# aes128_Wrap['parameters'] are absent + +aes192_Wrap = AlgorithmIdentifier() +aes192_Wrap['algorithm'] = id_aes128_Wrap +# aes192_Wrap['parameters'] are absent + +aes256_Wrap = AlgorithmIdentifier() +aes256_Wrap['algorithm'] = id_sha256 +# aes256_Wrap['parameters'] are absent + +tdes_Wrap = AlgorithmIdentifier() +tdes_Wrap['algorithm'] = id_alg_CMS3DESwrap +tdes_Wrap['parameters'] = univ.Null("") + +camellia128_Wrap = AlgorithmIdentifier() +camellia128_Wrap['algorithm'] = id_camellia128_Wrap +# camellia128_Wrap['parameters'] are absent + +camellia192_Wrap = AlgorithmIdentifier() +camellia192_Wrap['algorithm'] = id_camellia192_Wrap +# camellia192_Wrap['parameters'] are absent + +camellia256_Wrap = AlgorithmIdentifier() +camellia256_Wrap['algorithm'] = id_camellia256_Wrap +# camellia256_Wrap['parameters'] are absent + + +# Update the Algorithm Identifier map in rfc5280.py. +# Note that the ones that must not have parameters are not added to the map. + +_algorithmIdentifierMapUpdate = { + id_rsa_kem: GenericHybridParameters(), + id_kem_rsa: RsaKemParameters(), + id_kdf_kdf2: KDF2_HashFunction(), + id_kdf_kdf3: KDF3_HashFunction(), + id_sha1: univ.Null(), + id_sha224: univ.Null(), + id_sha256: univ.Null(), + id_sha384: univ.Null(), + id_sha512: univ.Null(), + id_alg_CMS3DESwrap: univ.Null(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc6010.py b/pyasn1_modules/rfc6010.py new file mode 100644 index 0000000..250e207 --- /dev/null +++ b/pyasn1_modules/rfc6010.py @@ -0,0 +1,88 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with assistance from asn1ate v.0.6.0. +# Modified by Russ Housley to add maps for use with opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Certificate Extension for CMS Content Constraints (CCC) +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc6010.txt +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + +MAX = float('inf') + + +AttributeType = rfc5280.AttributeType + +AttributeValue = rfc5280.AttributeValue + + +id_ct_anyContentType = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.0') + + +class AttrConstraint(univ.Sequence): + pass + +AttrConstraint.componentType = namedtype.NamedTypes( + namedtype.NamedType('attrType', AttributeType()), + namedtype.NamedType('attrValues', univ.SetOf( + componentType=AttributeValue()).subtype(subtypeSpec=constraint.ValueSizeConstraint(1, MAX))) +) + + +class AttrConstraintList(univ.SequenceOf): + pass + +AttrConstraintList.componentType = AttrConstraint() +AttrConstraintList.subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + + +class ContentTypeGeneration(univ.Enumerated): + pass + +ContentTypeGeneration.namedValues = namedval.NamedValues( + ('canSource', 0), + ('cannotSource', 1) +) + + +class ContentTypeConstraint(univ.Sequence): + pass + +ContentTypeConstraint.componentType = namedtype.NamedTypes( + namedtype.NamedType('contentType', univ.ObjectIdentifier()), + namedtype.DefaultedNamedType('canSource', ContentTypeGeneration().subtype(value='canSource')), + namedtype.OptionalNamedType('attrConstraints', AttrConstraintList()) +) + + +# CMS Content Constraints (CCC) Extension and Object Identifier + +id_pe_cmsContentConstraints = univ.ObjectIdentifier('1.3.6.1.5.5.7.1.18') + +class CMSContentConstraints(univ.SequenceOf): + pass + +CMSContentConstraints.componentType = ContentTypeConstraint() +CMSContentConstraints.subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + + +# Map of Certificate Extension OIDs to Extensions +# To be added to the ones that are in rfc5280.py + +_certificateExtensionsMap = { + id_pe_cmsContentConstraints: CMSContentConstraints(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMap) diff --git a/pyasn1_modules/rfc6019.py b/pyasn1_modules/rfc6019.py new file mode 100644 index 0000000..c6872c7 --- /dev/null +++ b/pyasn1_modules/rfc6019.py @@ -0,0 +1,45 @@ +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley. +# Modified by Russ Housley to add a map for use with opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# BinaryTime: An Alternate Format for Representing Date and Time +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc6019.txt + +from pyasn1.type import constraint +from pyasn1.type import univ + +from pyasn1_modules import rfc5652 + +MAX = float('inf') + + +# BinaryTime: Represent date and time as an integer + +class BinaryTime(univ.Integer): + pass + +BinaryTime.subtypeSpec = constraint.ValueRangeConstraint(0, MAX) + + +# CMS Attribute for representing signing time in BinaryTime + +id_aa_binarySigningTime = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.46') + +class BinarySigningTime(BinaryTime): + pass + + +# Map of Attribute Type OIDs to Attributes ia added to the +# ones that are in rfc5652.py + +_cmsAttributesMapUpdate = { + id_aa_binarySigningTime: BinarySigningTime(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) diff --git a/pyasn1_modules/rfc6031.py b/pyasn1_modules/rfc6031.py new file mode 100644 index 0000000..6e1bb22 --- /dev/null +++ b/pyasn1_modules/rfc6031.py @@ -0,0 +1,469 @@ +# +# 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 +# +# CMS Symmetric Key Package Content Type +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc6031.txt +# + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import opentype +from pyasn1.type import tag +from pyasn1.type import univ +from pyasn1.type import useful + +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc6019 + + +def _OID(*components): + output = [] + for x in tuple(components): + if isinstance(x, univ.ObjectIdentifier): + output.extend(list(x)) + else: + output.append(int(x)) + return univ.ObjectIdentifier(output) + + +MAX = float('inf') + +id_pskc = univ.ObjectIdentifier('1.2.840.113549.1.9.16.12') + + +# Symmetric Key Package Attributes + +id_pskc_manufacturer = _OID(id_pskc, 1) + +class at_pskc_manufacturer(char.UTF8String): + pass + + +id_pskc_serialNo = _OID(id_pskc, 2) + +class at_pskc_serialNo(char.UTF8String): + pass + + +id_pskc_model = _OID(id_pskc, 3) + +class at_pskc_model(char.UTF8String): + pass + + +id_pskc_issueNo = _OID(id_pskc, 4) + +class at_pskc_issueNo(char.UTF8String): + pass + + +id_pskc_deviceBinding = _OID(id_pskc, 5) + +class at_pskc_deviceBinding(char.UTF8String): + pass + + +id_pskc_deviceStartDate = _OID(id_pskc, 6) + +class at_pskc_deviceStartDate(useful.GeneralizedTime): + pass + + +id_pskc_deviceExpiryDate = _OID(id_pskc, 7) + +class at_pskc_deviceExpiryDate(useful.GeneralizedTime): + pass + + +id_pskc_moduleId = _OID(id_pskc, 8) + +class at_pskc_moduleId(char.UTF8String): + pass + + +id_pskc_deviceUserId = _OID(id_pskc, 26) + +class at_pskc_deviceUserId(char.UTF8String): + pass + + +# Symmetric Key Attributes + +id_pskc_keyId = _OID(id_pskc, 9) + +class at_pskc_keyUserId(char.UTF8String): + pass + + +id_pskc_algorithm = _OID(id_pskc, 10) + +class at_pskc_algorithm(char.UTF8String): + pass + + +id_pskc_issuer = _OID(id_pskc, 11) + +class at_pskc_issuer(char.UTF8String): + pass + + +id_pskc_keyProfileId = _OID(id_pskc, 12) + +class at_pskc_keyProfileId(char.UTF8String): + pass + + +id_pskc_keyReference = _OID(id_pskc, 13) + +class at_pskc_keyReference(char.UTF8String): + pass + + +id_pskc_friendlyName = _OID(id_pskc, 14) + +class FriendlyName(univ.Sequence): + pass + +FriendlyName.componentType = namedtype.NamedTypes( + namedtype.NamedType('friendlyName', char.UTF8String()), + namedtype.OptionalNamedType('friendlyNameLangTag', char.UTF8String()) +) + +class at_pskc_friendlyName(FriendlyName): + pass + + +id_pskc_algorithmParameters = _OID(id_pskc, 15) + +class Encoding(char.UTF8String): + pass + +Encoding.namedValues = namedval.NamedValues( + ('dec', "DECIMAL"), + ('hex', "HEXADECIMAL"), + ('alpha', "ALPHANUMERIC"), + ('b64', "BASE64"), + ('bin', "BINARY") +) + +Encoding.subtypeSpec = constraint.SingleValueConstraint( + "DECIMAL", "HEXADECIMAL", "ALPHANUMERIC", "BASE64", "BINARY" ) + +class ChallengeFormat(univ.Sequence): + pass + +ChallengeFormat.componentType = namedtype.NamedTypes( + namedtype.NamedType('encoding', Encoding()), + namedtype.DefaultedNamedType('checkDigit', + univ.Boolean().subtype(value=0)), + namedtype.NamedType('min', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(0, MAX))), + namedtype.NamedType('max', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(0, MAX))) +) + +class ResponseFormat(univ.Sequence): + pass + +ResponseFormat.componentType = namedtype.NamedTypes( + namedtype.NamedType('encoding', Encoding()), + namedtype.NamedType('length', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(0, MAX))), + namedtype.DefaultedNamedType('checkDigit', + univ.Boolean().subtype(value=0)) +) + +class PSKCAlgorithmParameters(univ.Choice): + pass + +PSKCAlgorithmParameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('suite', char.UTF8String()), + namedtype.NamedType('challengeFormat', ChallengeFormat().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.NamedType('responseFormat', ResponseFormat().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))) +) + +class at_pskc_algorithmParameters(PSKCAlgorithmParameters): + pass + + +id_pskc_counter = _OID(id_pskc, 16) + +class at_pskc_counter(univ.Integer): + pass + +at_pskc_counter.subtypeSpec = constraint.ValueRangeConstraint(0, MAX) + + +id_pskc_time = _OID(id_pskc, 17) + +class at_pskc_time(rfc6019.BinaryTime): + pass + + +id_pskc_timeInterval = _OID(id_pskc, 18) + +class at_pskc_timeInterval(univ.Integer): + pass + +at_pskc_timeInterval.subtypeSpec = constraint.ValueRangeConstraint(0, MAX) + + +id_pskc_timeDrift = _OID(id_pskc, 19) + +class at_pskc_timeDrift(univ.Integer): + pass + +at_pskc_timeDrift.subtypeSpec = constraint.ValueRangeConstraint(0, MAX) + + +id_pskc_valueMAC = _OID(id_pskc, 20) + +class ValueMac(univ.Sequence): + pass + +ValueMac.componentType = namedtype.NamedTypes( + namedtype.NamedType('macAlgorithm', char.UTF8String()), + namedtype.NamedType('mac', char.UTF8String()) +) + +class at_pskc_valueMAC(ValueMac): + pass + + +id_pskc_keyUserId = _OID(id_pskc, 27) + +class at_pskc_keyId(char.UTF8String): + pass + + +id_pskc_keyStartDate = _OID(id_pskc, 21) + +class at_pskc_keyStartDate(useful.GeneralizedTime): + pass + + +id_pskc_keyExpiryDate = _OID(id_pskc, 22) + +class at_pskc_keyExpiryDate(useful.GeneralizedTime): + pass + + +id_pskc_numberOfTransactions = _OID(id_pskc, 23) + +class at_pskc_numberOfTransactions(univ.Integer): + pass + +at_pskc_numberOfTransactions.subtypeSpec = constraint.ValueRangeConstraint(0, MAX) + + +id_pskc_keyUsages = _OID(id_pskc, 24) + +class PSKCKeyUsage(char.UTF8String): + pass + +PSKCKeyUsage.namedValues = namedval.NamedValues( + ('otp', "OTP"), + ('cr', "CR"), + ('encrypt', "Encrypt"), + ('integrity', "Integrity"), + ('verify', "Verify"), + ('unlock', "Unlock"), + ('decrypt', "Decrypt"), + ('keywrap', "KeyWrap"), + ('unwrap', "Unwrap"), + ('derive', "Derive"), + ('generate', "Generate") +) + +PSKCKeyUsage.subtypeSpec = constraint.SingleValueConstraint( + "OTP", "CR", "Encrypt", "Integrity", "Verify", "Unlock", + "Decrypt", "KeyWrap", "Unwrap", "Derive", "Generate" ) + +class PSKCKeyUsages(univ.SequenceOf): + pass + +PSKCKeyUsages.componentType = PSKCKeyUsage() + +class at_pskc_keyUsage(PSKCKeyUsages): + pass + + +id_pskc_pinPolicy = _OID(id_pskc, 25) + +class PINUsageMode(char.UTF8String): + pass + +PINUsageMode.namedValues = namedval.NamedValues( + ("local", "Local"), + ("prepend", "Prepend"), + ("append", "Append"), + ("algorithmic", "Algorithmic") +) + +PINUsageMode.subtypeSpec = constraint.SingleValueConstraint( + "Local", "Prepend", "Append", "Algorithmic" ) + +class PINPolicy(univ.Sequence): + pass + +PINPolicy.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('pinKeyId', char.UTF8String().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('pinUsageMode', PINUsageMode().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('maxFailedAttempts', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(0, MAX)).subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.OptionalNamedType('minLength', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(0, MAX)).subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.OptionalNamedType('maxLength', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(0, MAX)).subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))), + namedtype.OptionalNamedType('pinEncoding', Encoding().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 5))) +) + +class at_pskc_pinPolicy(PINPolicy): + pass + + +# Map of Symmetric Key Package Attribute OIDs to Attributes + +sKeyPkgAttributesMap = { + id_pskc_manufacturer: at_pskc_manufacturer(), + id_pskc_serialNo: at_pskc_serialNo(), + id_pskc_model: at_pskc_model(), + id_pskc_issueNo: at_pskc_issueNo(), + id_pskc_deviceBinding: at_pskc_deviceBinding(), + id_pskc_deviceStartDate: at_pskc_deviceStartDate(), + id_pskc_deviceExpiryDate: at_pskc_deviceExpiryDate(), + id_pskc_moduleId: at_pskc_moduleId(), + id_pskc_deviceUserId: at_pskc_deviceUserId(), +} + + +# Map of Symmetric Key Attribute OIDs to Attributes + +sKeyAttributesMap = { + id_pskc_keyId: at_pskc_keyId(), + id_pskc_algorithm: at_pskc_algorithm(), + id_pskc_issuer: at_pskc_issuer(), + id_pskc_keyProfileId: at_pskc_keyProfileId(), + id_pskc_keyReference: at_pskc_keyReference(), + id_pskc_friendlyName: at_pskc_friendlyName(), + id_pskc_algorithmParameters: at_pskc_algorithmParameters(), + id_pskc_counter: at_pskc_counter(), + id_pskc_time: at_pskc_time(), + id_pskc_timeInterval: at_pskc_timeInterval(), + id_pskc_timeDrift: at_pskc_timeDrift(), + id_pskc_valueMAC: at_pskc_valueMAC(), + id_pskc_keyUserId: at_pskc_keyUserId(), + id_pskc_keyStartDate: at_pskc_keyStartDate(), + id_pskc_keyExpiryDate: at_pskc_keyExpiryDate(), + id_pskc_numberOfTransactions: at_pskc_numberOfTransactions(), + id_pskc_keyUsages: at_pskc_keyUsage(), + id_pskc_pinPolicy: at_pskc_pinPolicy(), +} + + +# This definition replaces Attribute() from rfc5652.py; it is the same except +# that opentype is added with sKeyPkgAttributesMap and sKeyAttributesMap + +class AttributeType(univ.ObjectIdentifier): + pass + + +class AttributeValue(univ.Any): + pass + + +class SKeyAttribute(univ.Sequence): + pass + +SKeyAttribute.componentType = namedtype.NamedTypes( + namedtype.NamedType('attrType', AttributeType()), + namedtype.NamedType('attrValues', + univ.SetOf(componentType=AttributeValue()), + openType=opentype.OpenType('attrType', sKeyAttributesMap) + ) +) + + +class SKeyPkgAttribute(univ.Sequence): + pass + +SKeyPkgAttribute.componentType = namedtype.NamedTypes( + namedtype.NamedType('attrType', AttributeType()), + namedtype.NamedType('attrValues', + univ.SetOf(componentType=AttributeValue()), + openType=opentype.OpenType('attrType', sKeyPkgAttributesMap) + ) +) + + +# Symmetric Key Package Content Type + +id_ct_KP_sKeyPackage = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.25') + + +class KeyPkgVersion(univ.Integer): + pass + +KeyPkgVersion.namedValues = namedval.NamedValues( + ('v1', 1) +) + + +class OneSymmetricKey(univ.Sequence): + pass + +OneSymmetricKey.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('sKeyAttrs', + univ.SequenceOf(componentType=SKeyAttribute()).subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, MAX))), + namedtype.OptionalNamedType('sKey', univ.OctetString()) +) + +OneSymmetricKey.sizeSpec = univ.Sequence.sizeSpec + constraint.ValueSizeConstraint(1, 2) + + +class SymmetricKeys(univ.SequenceOf): + pass + +SymmetricKeys.componentType = OneSymmetricKey() +SymmetricKeys.subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + + +class SymmetricKeyPackage(univ.Sequence): + pass + +SymmetricKeyPackage.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', KeyPkgVersion().subtype(value='v1')), + namedtype.OptionalNamedType('sKeyPkgAttrs', + univ.SequenceOf(componentType=SKeyPkgAttribute()).subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, MAX), + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('sKeys', SymmetricKeys()) +) + + +# Map of Content Type OIDs to Content Types are +# added to the ones that are in rfc5652.py + +_cmsContentTypesMapUpdate = { + id_ct_KP_sKeyPackage: SymmetricKeyPackage(), +} + +rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate) diff --git a/pyasn1_modules/rfc6032.py b/pyasn1_modules/rfc6032.py new file mode 100644 index 0000000..563639a --- /dev/null +++ b/pyasn1_modules/rfc6032.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 +# +# CMS Encrypted Key Package Content Type +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc6032.txt +# + +from pyasn1.type import namedtype +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5083 + + +# Content Decryption Key Identifier attribute + +id_aa_KP_contentDecryptKeyID = univ.ObjectIdentifier('2.16.840.1.101.2.1.5.66') + +class ContentDecryptKeyID(univ.OctetString): + pass + +aa_content_decrypt_key_identifier = rfc5652.Attribute() +aa_content_decrypt_key_identifier['attrType'] = id_aa_KP_contentDecryptKeyID +aa_content_decrypt_key_identifier['attrValues'][0] = ContentDecryptKeyID() + + +# Encrypted Key Package Content Type + +id_ct_KP_encryptedKeyPkg = univ.ObjectIdentifier('2.16.840.1.101.2.1.2.78.2') + +class EncryptedKeyPackage(univ.Choice): + pass + +EncryptedKeyPackage.componentType = namedtype.NamedTypes( + namedtype.NamedType('encrypted', rfc5652.EncryptedData()), + namedtype.NamedType('enveloped', rfc5652.EnvelopedData().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('authEnveloped', rfc5083.AuthEnvelopedData().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +# Map of Attribute Type OIDs to Attributes are +# added to the ones that are in rfc5652.py + +_cmsAttributesMapUpdate = { + id_aa_KP_contentDecryptKeyID: ContentDecryptKeyID(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) + + +# Map of Content Type OIDs to Content Types are +# added to the ones that are in rfc5652.py + +_cmsContentTypesMapUpdate = { + id_ct_KP_encryptedKeyPkg: EncryptedKeyPackage(), +} + +rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate) diff --git a/pyasn1_modules/rfc6120.py b/pyasn1_modules/rfc6120.py new file mode 100644 index 0000000..ab25620 --- /dev/null +++ b/pyasn1_modules/rfc6120.py @@ -0,0 +1,43 @@ +# +# 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 +# +# Extensible Messaging and Presence Protocol (XMPP) +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc6120.txt +# + +from pyasn1.type import char +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + +MAX = float('inf') + + +# XmppAddr Identifier Type as specified in Section 13.7.1.4. of RFC 6120 + +id_pkix = rfc5280.id_pkix + +id_on = id_pkix + (8, ) + +id_on_xmppAddr = id_on + (5, ) + + +class XmppAddr(char.UTF8String): + pass + + +# Map of Other Name OIDs to Other Name is added to the +# ones that are in rfc5280.py + +_anotherNameMapUpdate = { + id_on_xmppAddr: XmppAddr(), +} + +rfc5280.anotherNameMap.update(_anotherNameMapUpdate) diff --git a/pyasn1_modules/rfc6170.py b/pyasn1_modules/rfc6170.py new file mode 100644 index 0000000..e287616 --- /dev/null +++ b/pyasn1_modules/rfc6170.py @@ -0,0 +1,17 @@ +# +# 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 +# +# Certificate Image in the Internet X.509 Public Key Infrastructure +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc6170.txt +# + +from pyasn1.type import univ + +id_logo_certImage = univ.ObjectIdentifier('1.3.6.1.5.5.7.20.3') diff --git a/pyasn1_modules/rfc6187.py b/pyasn1_modules/rfc6187.py new file mode 100644 index 0000000..4be0054 --- /dev/null +++ b/pyasn1_modules/rfc6187.py @@ -0,0 +1,22 @@ +# +# 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 +# +# X.509v3 Certificates for Secure Shell Authentication +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc6187.txt +# + +from pyasn1.type import univ + +id_pkix = univ.ObjectIdentifier('1.3.6.1.5.5.7') + +id_kp = id_pkix + (3, ) + +id_kp_secureShellClient = id_kp + (21, ) +id_kp_secureShellServer = id_kp + (22, ) diff --git a/pyasn1_modules/rfc6210.py b/pyasn1_modules/rfc6210.py new file mode 100644 index 0000000..28587b9 --- /dev/null +++ b/pyasn1_modules/rfc6210.py @@ -0,0 +1,42 @@ +# +# 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 +# +# Experiment for Hash Functions with Parameters in the CMS +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc6210.txt +# + +from pyasn1.type import constraint +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +id_alg_MD5_XOR_EXPERIMENT = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.13') + + +class MD5_XOR_EXPERIMENT(univ.OctetString): + pass + +MD5_XOR_EXPERIMENT.subtypeSpec = constraint.ValueSizeConstraint(64, 64) + + +mda_xor_md5_EXPERIMENT = rfc5280.AlgorithmIdentifier() +mda_xor_md5_EXPERIMENT['algorithm'] = id_alg_MD5_XOR_EXPERIMENT +mda_xor_md5_EXPERIMENT['parameters'] = MD5_XOR_EXPERIMENT() + + +# Map of Algorithm Identifier OIDs to Parameters added to the +# ones that are in rfc5280.py. + +_algorithmIdentifierMapUpdate = { + id_alg_MD5_XOR_EXPERIMENT: MD5_XOR_EXPERIMENT(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc6211.py b/pyasn1_modules/rfc6211.py new file mode 100644 index 0000000..abd7a86 --- /dev/null +++ b/pyasn1_modules/rfc6211.py @@ -0,0 +1,72 @@ +# +# 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 +# +# CMS Algorithm Identifier Protection Attribute +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc6211.txt +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5652 + + +# Imports from RFC 5652 + +DigestAlgorithmIdentifier = rfc5652.DigestAlgorithmIdentifier + +MessageAuthenticationCodeAlgorithm = rfc5652.MessageAuthenticationCodeAlgorithm + +SignatureAlgorithmIdentifier = rfc5652.SignatureAlgorithmIdentifier + + +# CMS Algorithm Protection attribute + +id_aa_cmsAlgorithmProtect = univ.ObjectIdentifier('1.2.840.113549.1.9.52') + + +class CMSAlgorithmProtection(univ.Sequence): + pass + +CMSAlgorithmProtection.componentType = namedtype.NamedTypes( + namedtype.NamedType('digestAlgorithm', DigestAlgorithmIdentifier()), + namedtype.OptionalNamedType('signatureAlgorithm', + SignatureAlgorithmIdentifier().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('macAlgorithm', + MessageAuthenticationCodeAlgorithm().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) +) + +CMSAlgorithmProtection.subtypeSpec = constraint.ConstraintsUnion( + constraint.WithComponentsConstraint( + ('signatureAlgorithm', constraint.ComponentPresentConstraint()), + ('macAlgorithm', constraint.ComponentAbsentConstraint())), + constraint.WithComponentsConstraint( + ('signatureAlgorithm', constraint.ComponentAbsentConstraint()), + ('macAlgorithm', constraint.ComponentPresentConstraint())) +) + + +aa_cmsAlgorithmProtection = rfc5652.Attribute() +aa_cmsAlgorithmProtection['attrType'] = id_aa_cmsAlgorithmProtect +aa_cmsAlgorithmProtection['attrValues'][0] = CMSAlgorithmProtection() + + +# Map of Attribute Type OIDs to Attributes are +# added to the ones that are in rfc5652.py + +_cmsAttributesMapUpdate = { + id_aa_cmsAlgorithmProtect: CMSAlgorithmProtection(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) \ No newline at end of file diff --git a/pyasn1_modules/rfc6402.py b/pyasn1_modules/rfc6402.py index faee07f..5490b05 100644 --- a/pyasn1_modules/rfc6402.py +++ b/pyasn1_modules/rfc6402.py @@ -3,18 +3,22 @@ # This file is part of pyasn1-modules software. # # Created by Stanisław Pitucha with asn1ate tool. -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Modified by Russ Housley to add a maps for CMC Control Attributes +# and CMC Content Types for use with opentypes. +# +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Certificate Management over CMS (CMC) Updates # # ASN.1 source from: -# http://www.ietf.org/rfc/rfc6402.txt +# https://www.rfc-editor.org/rfc/rfc6402.txt # from pyasn1.type import char from pyasn1.type import constraint from pyasn1.type import namedtype from pyasn1.type import namedval +from pyasn1.type import opentype from pyasn1.type import tag from pyasn1.type import univ from pyasn1.type import useful @@ -37,6 +41,10 @@ def _buildOid(*components): return univ.ObjectIdentifier(output) +# Since CMS Attributes and CMC Controls both use 'attrType', one map is used +cmcControlAttributesMap = rfc5652.cmsAttributesMap + + class ChangeSubjectName(univ.Sequence): pass @@ -90,7 +98,7 @@ class BodyPartPath(univ.SequenceOf): BodyPartPath.componentType = BodyPartID() -BodyPartPath.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +BodyPartPath.sizeSpec = constraint.ValueSizeConstraint(1, MAX) class BodyPartReference(univ.Choice): @@ -384,7 +392,9 @@ class TaggedAttribute(univ.Sequence): TaggedAttribute.componentType = namedtype.NamedTypes( namedtype.NamedType('bodyPartID', BodyPartID()), namedtype.NamedType('attrType', univ.ObjectIdentifier()), - namedtype.NamedType('attrValues', univ.SetOf(componentType=AttributeValue())) + namedtype.NamedType('attrValues', univ.SetOf(componentType=AttributeValue()), + openType=opentype.OpenType('attrType', cmcControlAttributesMap) + ) ) @@ -416,7 +426,7 @@ class BodyPartList(univ.SequenceOf): BodyPartList.componentType = BodyPartID() -BodyPartList.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +BodyPartList.sizeSpec = constraint.ValueSizeConstraint(1, MAX) id_cmc_responseBody = _buildOid(id_cmc, 37) @@ -481,7 +491,7 @@ class ExtensionReq(univ.SequenceOf): ExtensionReq.componentType = rfc5280.Extension() -ExtensionReq.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) +ExtensionReq.sizeSpec = constraint.ValueSizeConstraint(1, MAX) id_kp_cmcArchive = _buildOid(rfc5280.id_kp, 28) @@ -565,3 +575,54 @@ class NoSignatureValue(univ.OctetString): id_ad_cmc = _buildOid(rfc5280.id_ad, 12) id_alg_noSignature = _buildOid(id_pkix, 6, 2) + + +# Map of CMC Control OIDs to CMC Control Attributes + +_cmcControlAttributesMapUpdate = { + id_cmc_statusInfo: CMCStatusInfo(), + id_cmc_statusInfoV2: CMCStatusInfoV2(), + id_cmc_identification: char.UTF8String(), + id_cmc_identityProof: univ.OctetString(), + id_cmc_identityProofV2: IdentifyProofV2(), + id_cmc_dataReturn: univ.OctetString(), + id_cmc_transactionId: univ.Integer(), + id_cmc_senderNonce: univ.OctetString(), + id_cmc_recipientNonce: univ.OctetString(), + id_cmc_addExtensions: AddExtensions(), + id_cmc_encryptedPOP: EncryptedPOP(), + id_cmc_decryptedPOP: DecryptedPOP(), + id_cmc_lraPOPWitness: LraPopWitness(), + id_cmc_getCert: GetCert(), + id_cmc_getCRL: GetCRL(), + id_cmc_revokeRequest: RevokeRequest(), + id_cmc_regInfo: univ.OctetString(), + id_cmc_responseInfo: univ.OctetString(), + id_cmc_queryPending: univ.OctetString(), + id_cmc_popLinkRandom: univ.OctetString(), + id_cmc_popLinkWitness: univ.OctetString(), + id_cmc_popLinkWitnessV2: PopLinkWitnessV2(), + id_cmc_confirmCertAcceptance: CMCCertId(), + id_cmc_trustedAnchors: PublishTrustAnchors(), + id_cmc_authData: AuthPublish(), + id_cmc_batchRequests: BodyPartList(), + id_cmc_batchResponses: BodyPartList(), + id_cmc_publishCert: CMCPublicationInfo(), + id_cmc_modCertTemplate: ModCertTemplate(), + id_cmc_controlProcessed: ControlsProcessed(), + id_ExtensionReq: ExtensionReq(), +} + +cmcControlAttributesMap.update(_cmcControlAttributesMapUpdate) + + +# Map of CMC Content Type OIDs to CMC Content Types are added to +# the ones that are in rfc5652.py + +_cmsContentTypesMapUpdate = { + id_cct_PKIData: PKIData(), + id_cct_PKIResponse: PKIResponse(), +} + +rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate) + diff --git a/pyasn1_modules/rfc6482.py b/pyasn1_modules/rfc6482.py new file mode 100644 index 0000000..d213a46 --- /dev/null +++ b/pyasn1_modules/rfc6482.py @@ -0,0 +1,74 @@ +# +# 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 Route Origin Authorizations (ROAs) +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc6482.txt +# https://www.rfc-editor.org/errata/eid5881 +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5652 + +MAX = float('inf') + + +id_ct_routeOriginAuthz = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.24') + + +class ASID(univ.Integer): + pass + + +class IPAddress(univ.BitString): + pass + + +class ROAIPAddress(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('address', IPAddress()), + namedtype.OptionalNamedType('maxLength', univ.Integer()) + ) + + +class ROAIPAddressFamily(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('addressFamily', + univ.OctetString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(2, 3))), + namedtype.NamedType('addresses', + univ.SequenceOf(componentType=ROAIPAddress()).subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, MAX))) + ) + + +class RouteOriginAttestation(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', + univ.Integer().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0)).subtype(value=0)), + namedtype.NamedType('asID', ASID()), + namedtype.NamedType('ipAddrBlocks', + univ.SequenceOf(componentType=ROAIPAddressFamily()).subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, MAX))) + ) + + +# Map of Content Type OIDs to Content Types added to the +# ones that are in rfc5652.py + +_cmsContentTypesMapUpdate = { + id_ct_routeOriginAuthz: RouteOriginAttestation(), +} + +rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate) 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/pyasn1_modules/rfc6487.py b/pyasn1_modules/rfc6487.py new file mode 100644 index 0000000..d8c2f87 --- /dev/null +++ b/pyasn1_modules/rfc6487.py @@ -0,0 +1,22 @@ +# +# 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 +# +# Profile for X.509 PKIX Resource Certificates +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc6487.txt +# + +from pyasn1.type import univ + +id_pkix = univ.ObjectIdentifier('1.3.6.1.5.5.7') + +id_ad = id_pkix + (48, ) + +id_ad_rpkiManifest = id_ad + (10, ) +id_ad_signedObject = id_ad + (11, ) diff --git a/pyasn1_modules/rfc6664.py b/pyasn1_modules/rfc6664.py new file mode 100644 index 0000000..41629d8 --- /dev/null +++ b/pyasn1_modules/rfc6664.py @@ -0,0 +1,147 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with some assistance from asn1ate v.0.6.0. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# S/MIME Capabilities for Public Key Definitions +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc6664.txt +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5751 +from pyasn1_modules import rfc5480 +from pyasn1_modules import rfc4055 +from pyasn1_modules import rfc3279 + +MAX = float('inf') + + +# Imports from RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + + +# Imports from RFC 3279 + +dhpublicnumber = rfc3279.dhpublicnumber + +Dss_Parms = rfc3279.Dss_Parms + +id_dsa = rfc3279.id_dsa + +id_ecPublicKey = rfc3279.id_ecPublicKey + +rsaEncryption = rfc3279.rsaEncryption + + +# Imports from RFC 4055 + +id_mgf1 = rfc4055.id_mgf1 + +id_RSAES_OAEP = rfc4055.id_RSAES_OAEP + +id_RSASSA_PSS = rfc4055.id_RSASSA_PSS + + +# Imports from RFC 5480 + +ECParameters = rfc5480.ECParameters + +id_ecDH = rfc5480.id_ecDH + +id_ecMQV = rfc5480.id_ecMQV + + +# RSA + +class RSAKeySize(univ.Integer): + # suggested values are 1024, 2048, 3072, 4096, 7680, 8192, and 15360; + # however, the integer value is not limited to these suggestions + pass + + +class RSAKeyCapabilities(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('minKeySize', RSAKeySize()), + namedtype.OptionalNamedType('maxKeySize', RSAKeySize()) + ) + + +class RsaSsa_Pss_sig_caps(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('hashAlg', AlgorithmIdentifier()), + namedtype.OptionalNamedType('maskAlg', AlgorithmIdentifier()), + namedtype.DefaultedNamedType('trailerField', univ.Integer().subtype(value=1)) + ) + + +# Diffie-Hellman and DSA + +class DSAKeySize(univ.Integer): + subtypeSpec = constraint.SingleValueConstraint(1024, 2048, 3072, 7680, 15360) + + +class DSAKeyCapabilities(univ.Choice): + componentType = namedtype.NamedTypes( + namedtype.NamedType('keySizes', univ.Sequence(componentType=namedtype.NamedTypes( + namedtype.NamedType('minKeySize', + DSAKeySize()), + namedtype.OptionalNamedType('maxKeySize', + DSAKeySize()), + namedtype.OptionalNamedType('maxSizeP', + univ.Integer().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('maxSizeQ', + univ.Integer().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.OptionalNamedType('maxSizeG', + univ.Integer().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 3))) + )).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.NamedType('keyParams', + Dss_Parms().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 1))) + ) + + +# Elliptic Curve + +class EC_SMimeCaps(univ.SequenceOf): + componentType = ECParameters() + subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + + +# Update the SMIMECapabilities Attribute Map in rfc5751.py +# +# The map can either include an entry for scap-sa-rsaSSA-PSS or +# scap-pk-rsaSSA-PSS, but not both. One is associated with the +# public key and the other is associated with the signature +# algorithm; however, they use the same OID. If you need the +# other one in your application, copy the map into a local dict, +# adjust as needed, and pass the local dict to the decoder with +# openTypes=your_local_map. + +_smimeCapabilityMapUpdate = { + rsaEncryption: RSAKeyCapabilities(), + id_RSASSA_PSS: RSAKeyCapabilities(), + # id_RSASSA_PSS: RsaSsa_Pss_sig_caps(), + id_RSAES_OAEP: RSAKeyCapabilities(), + id_dsa: DSAKeyCapabilities(), + dhpublicnumber: DSAKeyCapabilities(), + id_ecPublicKey: EC_SMimeCaps(), + id_ecDH: EC_SMimeCaps(), + id_ecMQV: EC_SMimeCaps(), + id_mgf1: AlgorithmIdentifier(), +} + +rfc5751.smimeCapabilityMap.update(_smimeCapabilityMapUpdate) diff --git a/pyasn1_modules/rfc6955.py b/pyasn1_modules/rfc6955.py new file mode 100644 index 0000000..09f2d65 --- /dev/null +++ b/pyasn1_modules/rfc6955.py @@ -0,0 +1,108 @@ +# +# 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 +# +# Diffie-Hellman Proof-of-Possession Algorithms +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc6955.txt +# + +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc3279 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 + + +# Imports from RFC 5652 + +MessageDigest = rfc5652.MessageDigest + +IssuerAndSerialNumber = rfc5652.IssuerAndSerialNumber + + +# Imports from RFC 5280 + +id_pkix = rfc5280.id_pkix + + +# Imports from RFC 3279 + +Dss_Sig_Value = rfc3279.Dss_Sig_Value + +DomainParameters = rfc3279.DomainParameters + + +# Static DH Proof-of-Possession + +class DhSigStatic(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('issuerAndSerial', IssuerAndSerialNumber()), + namedtype.NamedType('hashValue', MessageDigest()) + ) + + +# Object Identifiers + +id_dh_sig_hmac_sha1 = id_pkix + (6, 3, ) + +id_dhPop_static_sha1_hmac_sha1 = univ.ObjectIdentifier(id_dh_sig_hmac_sha1) + + +id_alg_dh_pop = id_pkix + (6, 4, ) + +id_alg_dhPop_sha1 = univ.ObjectIdentifier(id_alg_dh_pop) + +id_alg_dhPop_sha224 = id_pkix + (6, 5, ) + +id_alg_dhPop_sha256 = id_pkix + (6, 6, ) + +id_alg_dhPop_sha384 = id_pkix + (6, 7, ) + +id_alg_dhPop_sha512 = id_pkix + (6, 8, ) + + +id_alg_dhPop_static_sha224_hmac_sha224 = id_pkix + (6, 15, ) + +id_alg_dhPop_static_sha256_hmac_sha256 = id_pkix + (6, 16, ) + +id_alg_dhPop_static_sha384_hmac_sha384 = id_pkix + (6, 17, ) + +id_alg_dhPop_static_sha512_hmac_sha512 = id_pkix + (6, 18, ) + + +id_alg_ecdhPop_static_sha224_hmac_sha224 = id_pkix + (6, 25, ) + +id_alg_ecdhPop_static_sha256_hmac_sha256 = id_pkix + (6, 26, ) + +id_alg_ecdhPop_static_sha384_hmac_sha384 = id_pkix + (6, 27, ) + +id_alg_ecdhPop_static_sha512_hmac_sha512 = id_pkix + (6, 28, ) + + +# Update the Algorithm Identifier map in rfc5280.py + +_algorithmIdentifierMapUpdate = { + id_alg_dh_pop: DomainParameters(), + id_alg_dhPop_sha224: DomainParameters(), + id_alg_dhPop_sha256: DomainParameters(), + id_alg_dhPop_sha384: DomainParameters(), + id_alg_dhPop_sha512: DomainParameters(), + id_dh_sig_hmac_sha1: univ.Null(""), + id_alg_dhPop_static_sha224_hmac_sha224: univ.Null(""), + id_alg_dhPop_static_sha256_hmac_sha256: univ.Null(""), + id_alg_dhPop_static_sha384_hmac_sha384: univ.Null(""), + id_alg_dhPop_static_sha512_hmac_sha512: univ.Null(""), + id_alg_ecdhPop_static_sha224_hmac_sha224: univ.Null(""), + id_alg_ecdhPop_static_sha256_hmac_sha256: univ.Null(""), + id_alg_ecdhPop_static_sha384_hmac_sha384: univ.Null(""), + id_alg_ecdhPop_static_sha512_hmac_sha512: univ.Null(""), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc6960.py b/pyasn1_modules/rfc6960.py new file mode 100644 index 0000000..e5f1305 --- /dev/null +++ b/pyasn1_modules/rfc6960.py @@ -0,0 +1,223 @@ +# +# 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 +# +# Online Certificate Status Protocol (OCSP) +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc6960.txt +# + +from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful + +from pyasn1_modules import rfc2560 +from pyasn1_modules import rfc5280 + +MAX = float('inf') + + +# Imports from RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier +AuthorityInfoAccessSyntax = rfc5280.AuthorityInfoAccessSyntax +Certificate = rfc5280.Certificate +CertificateSerialNumber = rfc5280.CertificateSerialNumber +CRLReason = rfc5280.CRLReason +Extensions = rfc5280.Extensions +GeneralName = rfc5280.GeneralName +Name = rfc5280.Name + +id_kp = rfc5280.id_kp + +id_ad_ocsp = rfc5280.id_ad_ocsp + + +# Imports from the original OCSP module in RFC 2560 + +AcceptableResponses = rfc2560.AcceptableResponses +ArchiveCutoff = rfc2560.ArchiveCutoff +CertStatus = rfc2560.CertStatus +KeyHash = rfc2560.KeyHash +OCSPResponse = rfc2560.OCSPResponse +OCSPResponseStatus = rfc2560.OCSPResponseStatus +ResponseBytes = rfc2560.ResponseBytes +RevokedInfo = rfc2560.RevokedInfo +UnknownInfo = rfc2560.UnknownInfo +Version = rfc2560.Version + +id_kp_OCSPSigning = rfc2560.id_kp_OCSPSigning + +id_pkix_ocsp = rfc2560.id_pkix_ocsp +id_pkix_ocsp_archive_cutoff = rfc2560.id_pkix_ocsp_archive_cutoff +id_pkix_ocsp_basic = rfc2560.id_pkix_ocsp_basic +id_pkix_ocsp_crl = rfc2560.id_pkix_ocsp_crl +id_pkix_ocsp_nocheck = rfc2560.id_pkix_ocsp_nocheck +id_pkix_ocsp_nonce = rfc2560.id_pkix_ocsp_nonce +id_pkix_ocsp_response = rfc2560.id_pkix_ocsp_response +id_pkix_ocsp_service_locator = rfc2560.id_pkix_ocsp_service_locator + + +# Additional object identifiers + +id_pkix_ocsp_pref_sig_algs = id_pkix_ocsp + (8, ) +id_pkix_ocsp_extended_revoke = id_pkix_ocsp + (9, ) + + +# Updated structures (mostly to improve openTypes support) + +class CertID(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('hashAlgorithm', AlgorithmIdentifier()), + namedtype.NamedType('issuerNameHash', univ.OctetString()), + namedtype.NamedType('issuerKeyHash', univ.OctetString()), + namedtype.NamedType('serialNumber', CertificateSerialNumber()) + ) + + +class SingleResponse(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('certID', CertID()), + namedtype.NamedType('certStatus', CertStatus()), + namedtype.NamedType('thisUpdate', useful.GeneralizedTime()), + namedtype.OptionalNamedType('nextUpdate', useful.GeneralizedTime().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('singleExtensions', Extensions().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) + ) + + +class ResponderID(univ.Choice): + componentType = namedtype.NamedTypes( + namedtype.NamedType('byName', Name().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('byKey', KeyHash().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) + ) + + +class ResponseData(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', Version('v1').subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('responderID', ResponderID()), + namedtype.NamedType('producedAt', useful.GeneralizedTime()), + namedtype.NamedType('responses', univ.SequenceOf( + componentType=SingleResponse())), + namedtype.OptionalNamedType('responseExtensions', Extensions().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) + ) + + +class BasicOCSPResponse(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('tbsResponseData', ResponseData()), + namedtype.NamedType('signatureAlgorithm', AlgorithmIdentifier()), + namedtype.NamedType('signature', univ.BitString()), + namedtype.OptionalNamedType('certs', univ.SequenceOf( + componentType=Certificate()).subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))) + ) + + +class Request(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('reqCert', CertID()), + namedtype.OptionalNamedType('singleRequestExtensions', Extensions().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) + ) + + +class Signature(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('signatureAlgorithm', AlgorithmIdentifier()), + namedtype.NamedType('signature', univ.BitString()), + namedtype.OptionalNamedType('certs', univ.SequenceOf( + componentType=Certificate()).subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))) + ) + + +class TBSRequest(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', Version('v1').subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('requestorName', GeneralName().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('requestList', univ.SequenceOf( + componentType=Request())), + namedtype.OptionalNamedType('requestExtensions', Extensions().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) + ) + + +class OCSPRequest(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('tbsRequest', TBSRequest()), + namedtype.OptionalNamedType('optionalSignature', Signature().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))) + ) + + +# Previously omitted structure + +class ServiceLocator(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('issuer', Name()), + namedtype.NamedType('locator', AuthorityInfoAccessSyntax()) + ) + + +# Additional structures + +class CrlID(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('crlUrl', char.IA5String().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('crlNum', univ.Integer().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('crlTime', useful.GeneralizedTime().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) + ) + + +class PreferredSignatureAlgorithm(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('sigIdentifier', AlgorithmIdentifier()), + namedtype.OptionalNamedType('certIdentifier', AlgorithmIdentifier()) + ) + + +class PreferredSignatureAlgorithms(univ.SequenceOf): + componentType = PreferredSignatureAlgorithm() + + + +# Response Type OID to Response Map + +ocspResponseMap = { + id_pkix_ocsp_basic: BasicOCSPResponse(), +} + + +# Map of Extension OIDs to Extensions added to the ones +# that are in rfc5280.py + +_certificateExtensionsMapUpdate = { + # Certificate Extension + id_pkix_ocsp_nocheck: univ.Null(""), + # OCSP Request Extensions + id_pkix_ocsp_nonce: univ.OctetString(), + id_pkix_ocsp_response: AcceptableResponses(), + id_pkix_ocsp_service_locator: ServiceLocator(), + id_pkix_ocsp_pref_sig_algs: PreferredSignatureAlgorithms(), + # OCSP Response Extensions + id_pkix_ocsp_crl: CrlID(), + id_pkix_ocsp_archive_cutoff: ArchiveCutoff(), + id_pkix_ocsp_extended_revoke: univ.Null(""), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMapUpdate) diff --git a/pyasn1_modules/rfc7030.py b/pyasn1_modules/rfc7030.py new file mode 100644 index 0000000..84b6dc5 --- /dev/null +++ b/pyasn1_modules/rfc7030.py @@ -0,0 +1,66 @@ +# +# 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 +# +# Enrollment over Secure Transport (EST) +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc7030.txt +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5652 + +MAX = float('inf') + + +# Imports from RFC 5652 + +Attribute = rfc5652.Attribute + + +# Asymmetric Decrypt Key Identifier Attribute + +id_aa_asymmDecryptKeyID = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.54') + +class AsymmetricDecryptKeyIdentifier(univ.OctetString): + pass + + +aa_asymmDecryptKeyID = Attribute() +aa_asymmDecryptKeyID['attrType'] = id_aa_asymmDecryptKeyID +aa_asymmDecryptKeyID['attrValues'][0] = AsymmetricDecryptKeyIdentifier() + + +# CSR Attributes + +class AttrOrOID(univ.Choice): + pass + +AttrOrOID.componentType = namedtype.NamedTypes( + namedtype.NamedType('oid', univ.ObjectIdentifier()), + namedtype.NamedType('attribute', Attribute()) +) + + +class CsrAttrs(univ.SequenceOf): + pass + +CsrAttrs.componentType = AttrOrOID() +CsrAttrs.subtypeSpec=constraint.ValueSizeConstraint(0, MAX) + + +# Update CMS Attribute Map + +_cmsAttributesMapUpdate = { + id_aa_asymmDecryptKeyID: AsymmetricDecryptKeyIdentifier(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) diff --git a/pyasn1_modules/rfc7191.py b/pyasn1_modules/rfc7191.py new file mode 100644 index 0000000..7c2be11 --- /dev/null +++ b/pyasn1_modules/rfc7191.py @@ -0,0 +1,261 @@ +# This file is being contributed to of pyasn1-modules software. +# +# Created by Russ Housley without assistance from the asn1ate tool. +# Modified by Russ Housley to add support for opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# CMS Key Package Receipt and Error Content Types +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc7191.txt + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import opentype +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 + +MAX = float('inf') + +DistinguishedName = rfc5280.DistinguishedName + + +# SingleAttribute is the same as Attribute in RFC 5652, except that the +# attrValues SET must have one and only one member + +class AttributeValue(univ.Any): + pass + + +class AttributeValues(univ.SetOf): + pass + +AttributeValues.componentType = AttributeValue() +AttributeValues.sizeSpec = univ.Set.sizeSpec + constraint.ValueSizeConstraint(1, 1) + + +class SingleAttribute(univ.Sequence): + pass + +SingleAttribute.componentType = namedtype.NamedTypes( + namedtype.NamedType('attrType', univ.ObjectIdentifier()), + namedtype.NamedType('attrValues', AttributeValues(), + openType=opentype.OpenType('attrType', rfc5652.cmsAttributesMap) + ) +) + + +# SIR Entity Name + +class SIREntityNameType(univ.ObjectIdentifier): + pass + + +class SIREntityNameValue(univ.Any): + pass + + +class SIREntityName(univ.Sequence): + pass + +SIREntityName.componentType = namedtype.NamedTypes( + namedtype.NamedType('sirenType', SIREntityNameType()), + namedtype.NamedType('sirenValue', univ.OctetString()) + # CONTAINING the DER-encoded SIREntityNameValue +) + + +class SIREntityNames(univ.SequenceOf): + pass + +SIREntityNames.componentType = SIREntityName() +SIREntityNames.sizeSpec=constraint.ValueSizeConstraint(1, MAX) + + +id_dn = univ.ObjectIdentifier('2.16.840.1.101.2.1.16.0') + + +class siren_dn(SIREntityName): + def __init__(self): + SIREntityName.__init__(self) + self['sirenType'] = id_dn + + +# Key Package Error CMS Content Type + +class EnumeratedErrorCode(univ.Enumerated): + pass + +# Error codes with values <= 33 are aligned with RFC 5934 +EnumeratedErrorCode.namedValues = namedval.NamedValues( + ('decodeFailure', 1), + ('badContentInfo', 2), + ('badSignedData', 3), + ('badEncapContent', 4), + ('badCertificate', 5), + ('badSignerInfo', 6), + ('badSignedAttrs', 7), + ('badUnsignedAttrs', 8), + ('missingContent', 9), + ('noTrustAnchor', 10), + ('notAuthorized', 11), + ('badDigestAlgorithm', 12), + ('badSignatureAlgorithm', 13), + ('unsupportedKeySize', 14), + ('unsupportedParameters', 15), + ('signatureFailure', 16), + ('insufficientMemory', 17), + ('incorrectTarget', 23), + ('missingSignature', 29), + ('resourcesBusy', 30), + ('versionNumberMismatch', 31), + ('revokedCertificate', 33), + ('ambiguousDecrypt', 60), + ('noDecryptKey', 61), + ('badEncryptedData', 62), + ('badEnvelopedData', 63), + ('badAuthenticatedData', 64), + ('badAuthEnvelopedData', 65), + ('badKeyAgreeRecipientInfo', 66), + ('badKEKRecipientInfo', 67), + ('badEncryptContent', 68), + ('badEncryptAlgorithm', 69), + ('missingCiphertext', 70), + ('decryptFailure', 71), + ('badMACAlgorithm', 72), + ('badAuthAttrs', 73), + ('badUnauthAttrs', 74), + ('invalidMAC', 75), + ('mismatchedDigestAlg', 76), + ('missingCertificate', 77), + ('tooManySigners', 78), + ('missingSignedAttributes', 79), + ('derEncodingNotUsed', 80), + ('missingContentHints', 81), + ('invalidAttributeLocation', 82), + ('badMessageDigest', 83), + ('badKeyPackage', 84), + ('badAttributes', 85), + ('attributeComparisonFailure', 86), + ('unsupportedSymmetricKeyPackage', 87), + ('unsupportedAsymmetricKeyPackage', 88), + ('constraintViolation', 89), + ('ambiguousDefaultValue', 90), + ('noMatchingRecipientInfo', 91), + ('unsupportedKeyWrapAlgorithm', 92), + ('badKeyTransRecipientInfo', 93), + ('other', 127) +) + + +class ErrorCodeChoice(univ.Choice): + pass + +ErrorCodeChoice.componentType = namedtype.NamedTypes( + namedtype.NamedType('enum', EnumeratedErrorCode()), + namedtype.NamedType('oid', univ.ObjectIdentifier()) +) + + +class KeyPkgID(univ.OctetString): + pass + + +class KeyPkgIdentifier(univ.Choice): + pass + +KeyPkgIdentifier.componentType = namedtype.NamedTypes( + namedtype.NamedType('pkgID', KeyPkgID()), + namedtype.NamedType('attribute', SingleAttribute()) +) + + +class KeyPkgVersion(univ.Integer): + pass + + +KeyPkgVersion.namedValues = namedval.NamedValues( + ('v1', 1), + ('v2', 2) +) + +KeyPkgVersion.subtypeSpec = constraint.ValueRangeConstraint(1, 65535) + + +id_ct_KP_keyPackageError = univ.ObjectIdentifier('2.16.840.1.101.2.1.2.78.6') + +class KeyPackageError(univ.Sequence): + pass + +KeyPackageError.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', KeyPkgVersion().subtype(value='v2')), + namedtype.OptionalNamedType('errorOf', KeyPkgIdentifier().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.NamedType('errorBy', SIREntityName()), + namedtype.NamedType('errorCode', ErrorCodeChoice()) +) + + +# Key Package Receipt CMS Content Type + +id_ct_KP_keyPackageReceipt = univ.ObjectIdentifier('2.16.840.1.101.2.1.2.78.3') + +class KeyPackageReceipt(univ.Sequence): + pass + +KeyPackageReceipt.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('version', KeyPkgVersion().subtype(value='v2')), + namedtype.NamedType('receiptOf', KeyPkgIdentifier()), + namedtype.NamedType('receivedBy', SIREntityName()) +) + + +# Key Package Receipt Request Attribute + +class KeyPkgReceiptReq(univ.Sequence): + pass + +KeyPkgReceiptReq.componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('encryptReceipt', univ.Boolean().subtype(value=0)), + namedtype.OptionalNamedType('receiptsFrom', SIREntityNames().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('receiptsTo', SIREntityNames()) +) + + +id_aa_KP_keyPkgIdAndReceiptReq = univ.ObjectIdentifier('2.16.840.1.101.2.1.5.65') + +class KeyPkgIdentifierAndReceiptReq(univ.Sequence): + pass + +KeyPkgIdentifierAndReceiptReq.componentType = namedtype.NamedTypes( + namedtype.NamedType('pkgID', KeyPkgID()), + namedtype.OptionalNamedType('receiptReq', KeyPkgReceiptReq()) +) + + +# Map of Attribute Type OIDs to Attributes are added to +# the ones that are in rfc5652.py + +_cmsAttributesMapUpdate = { + id_aa_KP_keyPkgIdAndReceiptReq: KeyPkgIdentifierAndReceiptReq(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) + + +# Map of CMC Content Type OIDs to CMC Content Types are added to +# the ones that are in rfc5652.py + +_cmsContentTypesMapUpdate = { + id_ct_KP_keyPackageError: KeyPackageError(), + id_ct_KP_keyPackageReceipt: KeyPackageReceipt(), +} + +rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate) diff --git a/pyasn1_modules/rfc7229.py b/pyasn1_modules/rfc7229.py new file mode 100644 index 0000000..e9bce2d --- /dev/null +++ b/pyasn1_modules/rfc7229.py @@ -0,0 +1,29 @@ +# +# 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 +# +# Object Identifiers for Test Certificate Policies +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc7229.txt +# + +from pyasn1.type import univ + + +id_pkix = univ.ObjectIdentifier('1.3.6.1.5.5.7') + +id_TEST = id_pkix + (13, ) + +id_TEST_certPolicyOne = id_TEST + (1, ) +id_TEST_certPolicyTwo = id_TEST + (2, ) +id_TEST_certPolicyThree = id_TEST + (3, ) +id_TEST_certPolicyFour = id_TEST + (4, ) +id_TEST_certPolicyFive = id_TEST + (5, ) +id_TEST_certPolicySix = id_TEST + (6, ) +id_TEST_certPolicySeven = id_TEST + (7, ) +id_TEST_certPolicyEight = id_TEST + (8, ) diff --git a/pyasn1_modules/rfc7292.py b/pyasn1_modules/rfc7292.py new file mode 100644 index 0000000..1c9f319 --- /dev/null +++ b/pyasn1_modules/rfc7292.py @@ -0,0 +1,357 @@ +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley with assistance from the asn1ate tool. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# PKCS #12: Personal Information Exchange Syntax v1.1 +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc7292.txt +# https://www.rfc-editor.org/errata_search.php?rfc=7292 + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import opentype +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc2315 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5958 + + +def _OID(*components): + output = [] + for x in tuple(components): + if isinstance(x, univ.ObjectIdentifier): + output.extend(list(x)) + else: + output.append(int(x)) + + return univ.ObjectIdentifier(output) + + +# Initialize the maps used in PKCS#12 + +pkcs12BagTypeMap = { } + +pkcs12CertBagMap = { } + +pkcs12CRLBagMap = { } + +pkcs12SecretBagMap = { } + + +# Imports from RFC 2315, RFC 5652, and RFC 5958 + +DigestInfo = rfc2315.DigestInfo + + +ContentInfo = rfc5652.ContentInfo + +PKCS12Attribute = rfc5652.Attribute + + +EncryptedPrivateKeyInfo = rfc5958.EncryptedPrivateKeyInfo + +PrivateKeyInfo = rfc5958.PrivateKeyInfo + + +# CMSSingleAttribute is the same as Attribute in RFC 5652 except the attrValues +# SET must have one and only one member + +class AttributeType(univ.ObjectIdentifier): + pass + + +class AttributeValue(univ.Any): + pass + + +class AttributeValues(univ.SetOf): + pass + +AttributeValues.componentType = AttributeValue() + + +class CMSSingleAttribute(univ.Sequence): + pass + +CMSSingleAttribute.componentType = namedtype.NamedTypes( + namedtype.NamedType('attrType', AttributeType()), + namedtype.NamedType('attrValues', + AttributeValues().subtype(sizeSpec=constraint.ValueSizeConstraint(1, 1)), + openType=opentype.OpenType('attrType', rfc5652.cmsAttributesMap) + ) +) + + +# Object identifier arcs + +rsadsi = _OID(1, 2, 840, 113549) + +pkcs = _OID(rsadsi, 1) + +pkcs_9 = _OID(pkcs, 9) + +certTypes = _OID(pkcs_9, 22) + +crlTypes = _OID(pkcs_9, 23) + +pkcs_12 = _OID(pkcs, 12) + + +# PBE Algorithm Identifiers and Parameters Structure + +pkcs_12PbeIds = _OID(pkcs_12, 1) + +pbeWithSHAAnd128BitRC4 = _OID(pkcs_12PbeIds, 1) + +pbeWithSHAAnd40BitRC4 = _OID(pkcs_12PbeIds, 2) + +pbeWithSHAAnd3_KeyTripleDES_CBC = _OID(pkcs_12PbeIds, 3) + +pbeWithSHAAnd2_KeyTripleDES_CBC = _OID(pkcs_12PbeIds, 4) + +pbeWithSHAAnd128BitRC2_CBC = _OID(pkcs_12PbeIds, 5) + +pbeWithSHAAnd40BitRC2_CBC = _OID(pkcs_12PbeIds, 6) + + +class Pkcs_12PbeParams(univ.Sequence): + pass + +Pkcs_12PbeParams.componentType = namedtype.NamedTypes( + namedtype.NamedType('salt', univ.OctetString()), + namedtype.NamedType('iterations', univ.Integer()) +) + + +# Bag types + +bagtypes = _OID(pkcs_12, 10, 1) + +class BAG_TYPE(univ.Sequence): + pass + +BAG_TYPE.componentType = namedtype.NamedTypes( + namedtype.NamedType('id', univ.ObjectIdentifier()), + namedtype.NamedType('unnamed1', univ.Any(), + openType=opentype.OpenType('attrType', pkcs12BagTypeMap) + ) +) + + +id_keyBag = _OID(bagtypes, 1) + +class KeyBag(PrivateKeyInfo): + pass + + +id_pkcs8ShroudedKeyBag = _OID(bagtypes, 2) + +class PKCS8ShroudedKeyBag(EncryptedPrivateKeyInfo): + pass + + +id_certBag = _OID(bagtypes, 3) + +class CertBag(univ.Sequence): + pass + +CertBag.componentType = namedtype.NamedTypes( + namedtype.NamedType('certId', univ.ObjectIdentifier()), + namedtype.NamedType('certValue', + univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)), + openType=opentype.OpenType('certId', pkcs12CertBagMap) + ) +) + + +x509Certificate = CertBag() +x509Certificate['certId'] = _OID(certTypes, 1) +x509Certificate['certValue'] = univ.OctetString() +# DER-encoded X.509 certificate stored in OCTET STRING + + +sdsiCertificate = CertBag() +sdsiCertificate['certId'] = _OID(certTypes, 2) +sdsiCertificate['certValue'] = char.IA5String() +# Base64-encoded SDSI certificate stored in IA5String + + +id_CRLBag = _OID(bagtypes, 4) + +class CRLBag(univ.Sequence): + pass + +CRLBag.componentType = namedtype.NamedTypes( + namedtype.NamedType('crlId', univ.ObjectIdentifier()), + namedtype.NamedType('crlValue', + univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)), + openType=opentype.OpenType('crlId', pkcs12CRLBagMap) + ) +) + + +x509CRL = CRLBag() +x509CRL['crlId'] = _OID(crlTypes, 1) +x509CRL['crlValue'] = univ.OctetString() +# DER-encoded X.509 CRL stored in OCTET STRING + + +id_secretBag = _OID(bagtypes, 5) + +class SecretBag(univ.Sequence): + pass + +SecretBag.componentType = namedtype.NamedTypes( + namedtype.NamedType('secretTypeId', univ.ObjectIdentifier()), + namedtype.NamedType('secretValue', + univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)), + openType=opentype.OpenType('secretTypeId', pkcs12SecretBagMap) + ) +) + + +id_safeContentsBag = _OID(bagtypes, 6) + +class SafeBag(univ.Sequence): + pass + +SafeBag.componentType = namedtype.NamedTypes( + namedtype.NamedType('bagId', univ.ObjectIdentifier()), + namedtype.NamedType('bagValue', + univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)), + openType=opentype.OpenType('bagId', pkcs12BagTypeMap) + ), + namedtype.OptionalNamedType('bagAttributes', + univ.SetOf(componentType=PKCS12Attribute()) + ) +) + + +class SafeContents(univ.SequenceOf): + pass + +SafeContents.componentType = SafeBag() + + +# The PFX PDU + +class AuthenticatedSafe(univ.SequenceOf): + pass + +AuthenticatedSafe.componentType = ContentInfo() +# Data if unencrypted +# EncryptedData if password-encrypted +# EnvelopedData if public key-encrypted + + +class MacData(univ.Sequence): + pass + +MacData.componentType = namedtype.NamedTypes( + namedtype.NamedType('mac', DigestInfo()), + namedtype.NamedType('macSalt', univ.OctetString()), + namedtype.DefaultedNamedType('iterations', univ.Integer().subtype(value=1)) + # Note: The default is for historical reasons and its use is deprecated +) + + +class PFX(univ.Sequence): + pass + +PFX.componentType = namedtype.NamedTypes( + namedtype.NamedType('version', + univ.Integer(namedValues=namedval.NamedValues(('v3', 3))) + ), + namedtype.NamedType('authSafe', ContentInfo()), + namedtype.OptionalNamedType('macData', MacData()) +) + + +# Local key identifier (also defined as certificateAttribute in rfc2985.py) + +pkcs_9_at_localKeyId = _OID(pkcs_9, 21) + +localKeyId = CMSSingleAttribute() +localKeyId['attrType'] = pkcs_9_at_localKeyId +localKeyId['attrValues'][0] = univ.OctetString() + + +# Friendly name (also defined as certificateAttribute in rfc2985.py) + +pkcs_9_ub_pkcs9String = univ.Integer(255) + +pkcs_9_ub_friendlyName = univ.Integer(pkcs_9_ub_pkcs9String) + +pkcs_9_at_friendlyName = _OID(pkcs_9, 20) + +class FriendlyName(char.BMPString): + pass + +FriendlyName.subtypeSpec = constraint.ValueSizeConstraint(1, pkcs_9_ub_friendlyName) + + +friendlyName = CMSSingleAttribute() +friendlyName['attrType'] = pkcs_9_at_friendlyName +friendlyName['attrValues'][0] = FriendlyName() + + +# Update the PKCS#12 maps + +_pkcs12BagTypeMap = { + id_keyBag: KeyBag(), + id_pkcs8ShroudedKeyBag: PKCS8ShroudedKeyBag(), + id_certBag: CertBag(), + id_CRLBag: CRLBag(), + id_secretBag: SecretBag(), + id_safeContentsBag: SafeBag(), +} + +pkcs12BagTypeMap.update(_pkcs12BagTypeMap) + + +_pkcs12CertBagMap = { + _OID(certTypes, 1): univ.OctetString(), + _OID(certTypes, 2): char.IA5String(), +} + +pkcs12CertBagMap.update(_pkcs12CertBagMap) + + +_pkcs12CRLBagMap = { + _OID(crlTypes, 1): univ.OctetString(), +} + +pkcs12CRLBagMap.update(_pkcs12CRLBagMap) + + +# Update the Algorithm Identifier map + +_algorithmIdentifierMapUpdate = { + pbeWithSHAAnd128BitRC4: Pkcs_12PbeParams(), + pbeWithSHAAnd40BitRC4: Pkcs_12PbeParams(), + pbeWithSHAAnd3_KeyTripleDES_CBC: Pkcs_12PbeParams(), + pbeWithSHAAnd2_KeyTripleDES_CBC: Pkcs_12PbeParams(), + pbeWithSHAAnd128BitRC2_CBC: Pkcs_12PbeParams(), + pbeWithSHAAnd40BitRC2_CBC: Pkcs_12PbeParams(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) + + +# Update the CMS Attribute map + +_cmsAttributesMapUpdate = { + pkcs_9_at_friendlyName: FriendlyName(), + pkcs_9_at_localKeyId: univ.OctetString(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) diff --git a/pyasn1_modules/rfc7296.py b/pyasn1_modules/rfc7296.py new file mode 100644 index 0000000..95a191a --- /dev/null +++ b/pyasn1_modules/rfc7296.py @@ -0,0 +1,32 @@ +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# IKEv2 Certificate Bundle +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc7296.txt + +from pyasn1.type import namedtype +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +class CertificateOrCRL(univ.Choice): + pass + +CertificateOrCRL.componentType = namedtype.NamedTypes( + namedtype.NamedType('cert', rfc5280.Certificate().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('crl', rfc5280.CertificateList().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class CertificateBundle(univ.SequenceOf): + pass + +CertificateBundle.componentType = CertificateOrCRL() diff --git a/pyasn1_modules/rfc7508.py b/pyasn1_modules/rfc7508.py new file mode 100644 index 0000000..6646024 --- /dev/null +++ b/pyasn1_modules/rfc7508.py @@ -0,0 +1,90 @@ +# +# 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 +# +# Securing Header Fields with S/MIME +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc7508.txt +# https://www.rfc-editor.org/errata/eid5875 +# + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import univ + +from pyasn1_modules import rfc5652 + +import string + +MAX = float('inf') + + +class Algorithm(univ.Enumerated): + namedValues = namedval.NamedValues( + ('canonAlgorithmSimple', 0), + ('canonAlgorithmRelaxed', 1) + ) + + +class HeaderFieldStatus(univ.Integer): + namedValues = namedval.NamedValues( + ('duplicated', 0), + ('deleted', 1), + ('modified', 2) + ) + + +class HeaderFieldName(char.VisibleString): + subtypeSpec = ( + constraint.PermittedAlphabetConstraint(*string.printable) - + constraint.PermittedAlphabetConstraint(':') + ) + + +class HeaderFieldValue(char.UTF8String): + pass + + +class HeaderField(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('field-Name', HeaderFieldName()), + namedtype.NamedType('field-Value', HeaderFieldValue()), + namedtype.DefaultedNamedType('field-Status', + HeaderFieldStatus().subtype(value='duplicated')) + ) + + +class HeaderFields(univ.SequenceOf): + componentType = HeaderField() + subtypeSpec = constraint.ValueSizeConstraint(1, MAX) + + +class SecureHeaderFields(univ.Set): + componentType = namedtype.NamedTypes( + namedtype.NamedType('canonAlgorithm', Algorithm()), + namedtype.NamedType('secHeaderFields', HeaderFields()) + ) + + +id_aa = univ.ObjectIdentifier((1, 2, 840, 113549, 1, 9, 16, 2, )) + +id_aa_secureHeaderFieldsIdentifier = id_aa + (55, ) + + + +# Map of Attribute Type OIDs to Attributes added to the +# ones that are in rfc5652.py + +_cmsAttributesMapUpdate = { + id_aa_secureHeaderFieldsIdentifier: SecureHeaderFields(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) + diff --git a/pyasn1_modules/rfc7585.py b/pyasn1_modules/rfc7585.py new file mode 100644 index 0000000..b3fd4a5 --- /dev/null +++ b/pyasn1_modules/rfc7585.py @@ -0,0 +1,50 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with some assistance from asn1ate v.0.6.0. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Network Access Identifier (NAI) Realm Name for Certificates +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc7585.txt +# + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +# NAI Realm Name for Certificates + +id_pkix = univ.ObjectIdentifier('1.3.6.1.5.5.7') + +id_on = id_pkix + (8, ) + +id_on_naiRealm = id_on + (8, ) + + +ub_naiRealm_length = univ.Integer(255) + + +class NAIRealm(char.UTF8String): + subtypeSpec = constraint.ValueSizeConstraint(1, ub_naiRealm_length) + + +naiRealm = rfc5280.AnotherName() +naiRealm['type-id'] = id_on_naiRealm +naiRealm['value'] = NAIRealm() + + +# Map of Other Name OIDs to Other Name is added to the +# ones that are in rfc5280.py + +_anotherNameMapUpdate = { + id_on_naiRealm: NAIRealm(), +} + +rfc5280.anotherNameMap.update(_anotherNameMapUpdate) diff --git a/pyasn1_modules/rfc7633.py b/pyasn1_modules/rfc7633.py new file mode 100644 index 0000000..f518440 --- /dev/null +++ b/pyasn1_modules/rfc7633.py @@ -0,0 +1,38 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with some assistance from asn1ate v.0.6.0. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Transport Layer Security (TLS) Feature Certificate Extension +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc7633.txt +# + +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +# TLS Features Extension + +id_pe = univ.ObjectIdentifier('1.3.6.1.5.5.7.1') + +id_pe_tlsfeature = id_pe + (24, ) + + +class Features(univ.SequenceOf): + componentType = univ.Integer() + + +# Map of Certificate Extension OIDs to Extensions added to the +# ones that are in rfc5280.py + +_certificateExtensionsMapUpdate = { + id_pe_tlsfeature: Features(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMapUpdate) diff --git a/pyasn1_modules/rfc7773.py b/pyasn1_modules/rfc7773.py new file mode 100644 index 0000000..0fee2aa --- /dev/null +++ b/pyasn1_modules/rfc7773.py @@ -0,0 +1,52 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with some assistance from asn1ate v.0.6.0. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Authentication Context Certificate Extension +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc7773.txt +# + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + +MAX = float('inf') + + +# Authentication Context Extension + +e_legnamnden = univ.ObjectIdentifier('1.2.752.201') + +id_eleg_ce = e_legnamnden + (5, ) + +id_ce_authContext = id_eleg_ce + (1, ) + + +class AuthenticationContext(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('contextType', char.UTF8String()), + namedtype.OptionalNamedType('contextInfo', char.UTF8String()) + ) + +class AuthenticationContexts(univ.SequenceOf): + componentType = AuthenticationContext() + subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + + +# Map of Certificate Extension OIDs to Extensions added to the +# ones that are in rfc5280.py + +_certificateExtensionsMapUpdate = { + id_ce_authContext: AuthenticationContexts(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMapUpdate) diff --git a/pyasn1_modules/rfc7894.py b/pyasn1_modules/rfc7894.py new file mode 100644 index 0000000..4193643 --- /dev/null +++ b/pyasn1_modules/rfc7894.py @@ -0,0 +1,92 @@ +# +# 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 +# +# Alternative Challenge Password Attributes for EST +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc7894.txt +# + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc6402 +from pyasn1_modules import rfc7191 + + +# SingleAttribute is the same as Attribute in RFC 5652, except that the +# attrValues SET must have one and only one member + +Attribute = rfc7191.SingleAttribute + + +# DirectoryString is the same as RFC 5280, except the length is limited to 255 + +class DirectoryString(univ.Choice): + pass + +DirectoryString.componentType = namedtype.NamedTypes( + namedtype.NamedType('teletexString', char.TeletexString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, 255))), + namedtype.NamedType('printableString', char.PrintableString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, 255))), + namedtype.NamedType('universalString', char.UniversalString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, 255))), + namedtype.NamedType('utf8String', char.UTF8String().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, 255))), + namedtype.NamedType('bmpString', char.BMPString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, 255))) +) + + +# OTP Challenge Attribute + +id_aa_otpChallenge = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.56') + +ub_aa_otpChallenge = univ.Integer(255) + +otpChallenge = Attribute() +otpChallenge['attrType'] = id_aa_otpChallenge +otpChallenge['attrValues'][0] = DirectoryString() + + +# Revocation Challenge Attribute + +id_aa_revocationChallenge = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.57') + +ub_aa_revocationChallenge = univ.Integer(255) + +revocationChallenge = Attribute() +revocationChallenge['attrType'] = id_aa_revocationChallenge +revocationChallenge['attrValues'][0] = DirectoryString() + + +# EST Identity Linking Attribute + +id_aa_estIdentityLinking = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.58') + +ub_aa_est_identity_linking = univ.Integer(255) + +estIdentityLinking = Attribute() +estIdentityLinking['attrType'] = id_aa_estIdentityLinking +estIdentityLinking['attrValues'][0] = DirectoryString() + + +# Map of Attribute Type OIDs to Attributes added to the +# ones that are in rfc6402.py + +_cmcControlAttributesMapUpdate = { + id_aa_otpChallenge: DirectoryString(), + id_aa_revocationChallenge: DirectoryString(), + id_aa_estIdentityLinking: DirectoryString(), +} + +rfc6402.cmcControlAttributesMap.update(_cmcControlAttributesMapUpdate) diff --git a/pyasn1_modules/rfc7906.py b/pyasn1_modules/rfc7906.py new file mode 100644 index 0000000..fa5f6b0 --- /dev/null +++ b/pyasn1_modules/rfc7906.py @@ -0,0 +1,736 @@ +# +# 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 +# +# NSA's CMS Key Management Attributes +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc7906.txt +# https://www.rfc-editor.org/errata/eid5850 +# + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc2634 +from pyasn1_modules import rfc4108 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc6010 +from pyasn1_modules import rfc6019 +from pyasn1_modules import rfc7191 + +MAX = float('inf') + + +# Imports From RFC 2634 + +id_aa_contentHint = rfc2634.id_aa_contentHint + +ContentHints = rfc2634.ContentHints + +id_aa_securityLabel = rfc2634.id_aa_securityLabel + +SecurityPolicyIdentifier = rfc2634.SecurityPolicyIdentifier + +SecurityClassification = rfc2634.SecurityClassification + +ESSPrivacyMark = rfc2634.ESSPrivacyMark + +SecurityCategories= rfc2634.SecurityCategories + +ESSSecurityLabel = rfc2634.ESSSecurityLabel + + +# Imports From RFC 4108 + +id_aa_communityIdentifiers = rfc4108.id_aa_communityIdentifiers + +CommunityIdentifier = rfc4108.CommunityIdentifier + +CommunityIdentifiers = rfc4108.CommunityIdentifiers + + +# Imports From RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + +Name = rfc5280.Name + +Certificate = rfc5280.Certificate + +GeneralNames = rfc5280.GeneralNames + +GeneralName = rfc5280.GeneralName + + +SubjectInfoAccessSyntax = rfc5280.SubjectInfoAccessSyntax + +id_pkix = rfc5280.id_pkix + +id_pe = rfc5280.id_pe + +id_pe_subjectInfoAccess = rfc5280.id_pe_subjectInfoAccess + + +# Imports From RFC 6010 + +CMSContentConstraints = rfc6010.CMSContentConstraints + + +# Imports From RFC 6019 + +BinaryTime = rfc6019.BinaryTime + +id_aa_binarySigningTime = rfc6019.id_aa_binarySigningTime + +BinarySigningTime = rfc6019.BinarySigningTime + + +# Imports From RFC 5652 + +Attribute = rfc5652.Attribute + +CertificateSet = rfc5652.CertificateSet + +CertificateChoices = rfc5652.CertificateChoices + +id_contentType = rfc5652.id_contentType + +ContentType = rfc5652.ContentType + +id_messageDigest = rfc5652.id_messageDigest + +MessageDigest = rfc5652.MessageDigest + + +# Imports From RFC 7191 + +SIREntityName = rfc7191.SIREntityName + +id_aa_KP_keyPkgIdAndReceiptReq = rfc7191.id_aa_KP_keyPkgIdAndReceiptReq + +KeyPkgIdentifierAndReceiptReq = rfc7191.KeyPkgIdentifierAndReceiptReq + + +# Key Province Attribute + +id_aa_KP_keyProvinceV2 = univ.ObjectIdentifier('2.16.840.1.101.2.1.5.71') + + +class KeyProvinceV2(univ.ObjectIdentifier): + pass + + +aa_keyProvince_v2 = Attribute() +aa_keyProvince_v2['attrType'] = id_aa_KP_keyProvinceV2 +aa_keyProvince_v2['attrValues'][0] = KeyProvinceV2() + + +# Manifest Attribute + +id_aa_KP_manifest = univ.ObjectIdentifier('2.16.840.1.101.2.1.5.72') + + +class ShortTitle(char.PrintableString): + pass + + +class Manifest(univ.SequenceOf): + pass + +Manifest.componentType = ShortTitle() +Manifest.subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + + +aa_manifest = Attribute() +aa_manifest['attrType'] = id_aa_KP_manifest +aa_manifest['attrValues'][0] = Manifest() + + +# Key Algorithm Attribute + +id_kma_keyAlgorithm = univ.ObjectIdentifier('2.16.840.1.101.2.1.13.1') + + +class KeyAlgorithm(univ.Sequence): + pass + +KeyAlgorithm.componentType = namedtype.NamedTypes( + namedtype.NamedType('keyAlg', univ.ObjectIdentifier()), + namedtype.OptionalNamedType('checkWordAlg', univ.ObjectIdentifier().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.OptionalNamedType('crcAlg', univ.ObjectIdentifier().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) +) + + +aa_keyAlgorithm = Attribute() +aa_keyAlgorithm['attrType'] = id_kma_keyAlgorithm +aa_keyAlgorithm['attrValues'][0] = KeyAlgorithm() + + +# User Certificate Attribute + +id_at_userCertificate = univ.ObjectIdentifier('2.5.4.36') + + +aa_userCertificate = Attribute() +aa_userCertificate['attrType'] = id_at_userCertificate +aa_userCertificate['attrValues'][0] = Certificate() + + +# Key Package Receivers Attribute + +id_kma_keyPkgReceiversV2 = univ.ObjectIdentifier('2.16.840.1.101.2.1.13.16') + + +class KeyPkgReceiver(univ.Choice): + pass + +KeyPkgReceiver.componentType = namedtype.NamedTypes( + namedtype.NamedType('sirEntity', SIREntityName().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('community', CommunityIdentifier().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class KeyPkgReceiversV2(univ.SequenceOf): + pass + +KeyPkgReceiversV2.componentType = KeyPkgReceiver() +KeyPkgReceiversV2.subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + + +aa_keyPackageReceivers_v2 = Attribute() +aa_keyPackageReceivers_v2['attrType'] = id_kma_keyPkgReceiversV2 +aa_keyPackageReceivers_v2['attrValues'][0] = KeyPkgReceiversV2() + + +# TSEC Nomenclature Attribute + +id_kma_TSECNomenclature = univ.ObjectIdentifier('2.16.840.1.101.2.1.13.3') + + +class CharEdition(char.PrintableString): + pass + + +class CharEditionRange(univ.Sequence): + pass + +CharEditionRange.componentType = namedtype.NamedTypes( + namedtype.NamedType('firstCharEdition', CharEdition()), + namedtype.NamedType('lastCharEdition', CharEdition()) +) + + +class NumEdition(univ.Integer): + pass + +NumEdition.subtypeSpec = constraint.ValueRangeConstraint(0, 308915776) + + +class NumEditionRange(univ.Sequence): + pass + +NumEditionRange.componentType = namedtype.NamedTypes( + namedtype.NamedType('firstNumEdition', NumEdition()), + namedtype.NamedType('lastNumEdition', NumEdition()) +) + + +class EditionID(univ.Choice): + pass + +EditionID.componentType = namedtype.NamedTypes( + namedtype.NamedType('char', univ.Choice(componentType=namedtype.NamedTypes( + namedtype.NamedType('charEdition', CharEdition().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('charEditionRange', CharEditionRange().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))) + )) + ), + namedtype.NamedType('num', univ.Choice(componentType=namedtype.NamedTypes( + namedtype.NamedType('numEdition', NumEdition().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), + namedtype.NamedType('numEditionRange', NumEditionRange().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4))) + )) + ) +) + + +class Register(univ.Integer): + pass + +Register.subtypeSpec = constraint.ValueRangeConstraint(0, 2147483647) + + +class RegisterRange(univ.Sequence): + pass + +RegisterRange.componentType = namedtype.NamedTypes( + namedtype.NamedType('firstRegister', Register()), + namedtype.NamedType('lastRegister', Register()) +) + + +class RegisterID(univ.Choice): + pass + +RegisterID.componentType = namedtype.NamedTypes( + namedtype.NamedType('register', Register().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 5))), + namedtype.NamedType('registerRange', RegisterRange().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 6))) +) + + +class SegmentNumber(univ.Integer): + pass + +SegmentNumber.subtypeSpec = constraint.ValueRangeConstraint(1, 127) + + +class SegmentRange(univ.Sequence): + pass + +SegmentRange.componentType = namedtype.NamedTypes( + namedtype.NamedType('firstSegment', SegmentNumber()), + namedtype.NamedType('lastSegment', SegmentNumber()) +) + + +class SegmentID(univ.Choice): + pass + +SegmentID.componentType = namedtype.NamedTypes( + namedtype.NamedType('segmentNumber', SegmentNumber().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 7))), + namedtype.NamedType('segmentRange', SegmentRange().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 8))) +) + + +class TSECNomenclature(univ.Sequence): + pass + +TSECNomenclature.componentType = namedtype.NamedTypes( + namedtype.NamedType('shortTitle', ShortTitle()), + namedtype.OptionalNamedType('editionID', EditionID()), + namedtype.OptionalNamedType('registerID', RegisterID()), + namedtype.OptionalNamedType('segmentID', SegmentID()) +) + + +aa_tsecNomenclature = Attribute() +aa_tsecNomenclature['attrType'] = id_kma_TSECNomenclature +aa_tsecNomenclature['attrValues'][0] = TSECNomenclature() + + +# Key Purpose Attribute + +id_kma_keyPurpose = univ.ObjectIdentifier('2.16.840.1.101.2.1.13.13') + + +class KeyPurpose(univ.Enumerated): + pass + +KeyPurpose.namedValues = namedval.NamedValues( + ('n-a', 0), + ('a', 65), + ('b', 66), + ('l', 76), + ('m', 77), + ('r', 82), + ('s', 83), + ('t', 84), + ('v', 86), + ('x', 88), + ('z', 90) +) + + +aa_keyPurpose = Attribute() +aa_keyPurpose['attrType'] = id_kma_keyPurpose +aa_keyPurpose['attrValues'][0] = KeyPurpose() + + +# Key Use Attribute + +id_kma_keyUse = univ.ObjectIdentifier('2.16.840.1.101.2.1.13.14') + + +class KeyUse(univ.Enumerated): + pass + +KeyUse.namedValues = namedval.NamedValues( + ('n-a', 0), + ('ffk', 1), + ('kek', 2), + ('kpk', 3), + ('msk', 4), + ('qkek', 5), + ('tek', 6), + ('tsk', 7), + ('trkek', 8), + ('nfk', 9), + ('effk', 10), + ('ebfk', 11), + ('aek', 12), + ('wod', 13), + ('kesk', 246), + ('eik', 247), + ('ask', 248), + ('kmk', 249), + ('rsk', 250), + ('csk', 251), + ('sak', 252), + ('rgk', 253), + ('cek', 254), + ('exk', 255) +) + + +aa_keyUse = Attribute() +aa_keyPurpose['attrType'] = id_kma_keyUse +aa_keyPurpose['attrValues'][0] = KeyUse() + + +# Transport Key Attribute + +id_kma_transportKey = univ.ObjectIdentifier('2.16.840.1.101.2.1.13.15') + + +class TransOp(univ.Enumerated): + pass + +TransOp.namedValues = namedval.NamedValues( + ('transport', 1), + ('operational', 2) +) + + +aa_transportKey = Attribute() +aa_transportKey['attrType'] = id_kma_transportKey +aa_transportKey['attrValues'][0] = TransOp() + + +# Key Distribution Period Attribute + +id_kma_keyDistPeriod = univ.ObjectIdentifier('2.16.840.1.101.2.1.13.5') + + +class KeyDistPeriod(univ.Sequence): + pass + +KeyDistPeriod.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('doNotDistBefore', BinaryTime().subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('doNotDistAfter', BinaryTime()) +) + + +aa_keyDistributionPeriod = Attribute() +aa_keyDistributionPeriod['attrType'] = id_kma_keyDistPeriod +aa_keyDistributionPeriod['attrValues'][0] = KeyDistPeriod() + + +# Key Validity Period Attribute + +id_kma_keyValidityPeriod = univ.ObjectIdentifier('2.16.840.1.101.2.1.13.6') + + +class KeyValidityPeriod(univ.Sequence): + pass + +KeyValidityPeriod.componentType = namedtype.NamedTypes( + namedtype.NamedType('doNotUseBefore', BinaryTime()), + namedtype.OptionalNamedType('doNotUseAfter', BinaryTime()) +) + + +aa_keyValidityPeriod = Attribute() +aa_keyValidityPeriod['attrType'] = id_kma_keyValidityPeriod +aa_keyValidityPeriod['attrValues'][0] = KeyValidityPeriod() + + +# Key Duration Attribute + +id_kma_keyDuration = univ.ObjectIdentifier('2.16.840.1.101.2.1.13.7') + + +ub_KeyDuration_months = univ.Integer(72) + +ub_KeyDuration_hours = univ.Integer(96) + +ub_KeyDuration_days = univ.Integer(732) + +ub_KeyDuration_weeks = univ.Integer(104) + +ub_KeyDuration_years = univ.Integer(100) + + +class KeyDuration(univ.Choice): + pass + +KeyDuration.componentType = namedtype.NamedTypes( + namedtype.NamedType('hours', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(1, ub_KeyDuration_hours)).subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('days', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(1, ub_KeyDuration_days))), + namedtype.NamedType('weeks', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(1, ub_KeyDuration_weeks)).subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('months', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(1, ub_KeyDuration_months)).subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))), + namedtype.NamedType('years', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(1, ub_KeyDuration_years)).subtype( + implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))) +) + + +aa_keyDurationPeriod = Attribute() +aa_keyDurationPeriod['attrType'] = id_kma_keyDuration +aa_keyDurationPeriod['attrValues'][0] = KeyDuration() + + +# Classification Attribute + +id_aa_KP_classification = univ.ObjectIdentifier(id_aa_securityLabel) + + +id_enumeratedPermissiveAttributes = univ.ObjectIdentifier('2.16.840.1.101.2.1.8.3.1') + +id_enumeratedRestrictiveAttributes = univ.ObjectIdentifier('2.16.840.1.101.2.1.8.3.4') + +id_informativeAttributes = univ.ObjectIdentifier('2.16.840.1.101.2.1.8.3.3') + + +class SecurityAttribute(univ.Integer): + pass + +SecurityAttribute.subtypeSpec = constraint.ValueRangeConstraint(0, MAX) + + +class EnumeratedTag(univ.Sequence): + pass + +EnumeratedTag.componentType = namedtype.NamedTypes( + namedtype.NamedType('tagName', univ.ObjectIdentifier()), + namedtype.NamedType('attributeList', univ.SetOf(componentType=SecurityAttribute())) +) + + +class FreeFormField(univ.Choice): + pass + +FreeFormField.componentType = namedtype.NamedTypes( + namedtype.NamedType('bitSetAttributes', univ.BitString()), # Not permitted in RFC 7906 + namedtype.NamedType('securityAttributes', univ.SetOf(componentType=SecurityAttribute())) +) + + +class InformativeTag(univ.Sequence): + pass + +InformativeTag.componentType = namedtype.NamedTypes( + namedtype.NamedType('tagName', univ.ObjectIdentifier()), + namedtype.NamedType('attributes', FreeFormField()) +) + + +class Classification(ESSSecurityLabel): + pass + + +aa_classification = Attribute() +aa_classification['attrType'] = id_aa_KP_classification +aa_classification['attrValues'][0] = Classification() + + +# Split Identifier Attribute + +id_kma_splitID = univ.ObjectIdentifier('2.16.840.1.101.2.1.13.11') + + +class SplitID(univ.Sequence): + pass + +SplitID.componentType = namedtype.NamedTypes( + namedtype.NamedType('half', univ.Enumerated( + namedValues=namedval.NamedValues(('a', 0), ('b', 1)))), + namedtype.OptionalNamedType('combineAlg', AlgorithmIdentifier()) +) + + +aa_splitIdentifier = Attribute() +aa_splitIdentifier['attrType'] = id_kma_splitID +aa_splitIdentifier['attrValues'][0] = SplitID() + + +# Key Package Type Attribute + +id_kma_keyPkgType = univ.ObjectIdentifier('2.16.840.1.101.2.1.13.12') + + +class KeyPkgType(univ.ObjectIdentifier): + pass + + +aa_keyPackageType = Attribute() +aa_keyPackageType['attrType'] = id_kma_keyPkgType +aa_keyPackageType['attrValues'][0] = KeyPkgType() + + +# Signature Usage Attribute + +id_kma_sigUsageV3 = univ.ObjectIdentifier('2.16.840.1.101.2.1.13.22') + + +class SignatureUsage(CMSContentConstraints): + pass + + +aa_signatureUsage_v3 = Attribute() +aa_signatureUsage_v3['attrType'] = id_kma_sigUsageV3 +aa_signatureUsage_v3['attrValues'][0] = SignatureUsage() + + +# Other Certificate Format Attribute + +id_kma_otherCertFormats = univ.ObjectIdentifier('2.16.840.1.101.2.1.13.19') + + +aa_otherCertificateFormats = Attribute() +aa_signatureUsage_v3['attrType'] = id_kma_otherCertFormats +aa_signatureUsage_v3['attrValues'][0] = CertificateChoices() + + +# PKI Path Attribute + +id_at_pkiPath = univ.ObjectIdentifier('2.5.4.70') + + +class PkiPath(univ.SequenceOf): + pass + +PkiPath.componentType = Certificate() +PkiPath.subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + + +aa_pkiPath = Attribute() +aa_pkiPath['attrType'] = id_at_pkiPath +aa_pkiPath['attrValues'][0] = PkiPath() + + +# Useful Certificates Attribute + +id_kma_usefulCerts = univ.ObjectIdentifier('2.16.840.1.101.2.1.13.20') + + +aa_usefulCertificates = Attribute() +aa_usefulCertificates['attrType'] = id_kma_usefulCerts +aa_usefulCertificates['attrValues'][0] = CertificateSet() + + +# Key Wrap Attribute + +id_kma_keyWrapAlgorithm = univ.ObjectIdentifier('2.16.840.1.101.2.1.13.21') + + +aa_keyWrapAlgorithm = Attribute() +aa_keyWrapAlgorithm['attrType'] = id_kma_keyWrapAlgorithm +aa_keyWrapAlgorithm['attrValues'][0] = AlgorithmIdentifier() + + +# Content Decryption Key Identifier Attribute + +id_aa_KP_contentDecryptKeyID = univ.ObjectIdentifier('2.16.840.1.101.2.1.5.66') + + +class ContentDecryptKeyID(univ.OctetString): + pass + + +aa_contentDecryptKeyIdentifier = Attribute() +aa_contentDecryptKeyIdentifier['attrType'] = id_aa_KP_contentDecryptKeyID +aa_contentDecryptKeyIdentifier['attrValues'][0] = ContentDecryptKeyID() + + +# Certificate Pointers Attribute + +aa_certificatePointers = Attribute() +aa_certificatePointers['attrType'] = id_pe_subjectInfoAccess +aa_certificatePointers['attrValues'][0] = SubjectInfoAccessSyntax() + + +# CRL Pointers Attribute + +id_aa_KP_crlPointers = univ.ObjectIdentifier('2.16.840.1.101.2.1.5.70') + + +aa_cRLDistributionPoints = Attribute() +aa_cRLDistributionPoints['attrType'] = id_aa_KP_crlPointers +aa_cRLDistributionPoints['attrValues'][0] = GeneralNames() + + +# Extended Error Codes + +id_errorCodes = univ.ObjectIdentifier('2.16.840.1.101.2.1.22') + +id_missingKeyType = univ.ObjectIdentifier('2.16.840.1.101.2.1.22.1') + +id_privacyMarkTooLong = univ.ObjectIdentifier('2.16.840.1.101.2.1.22.2') + +id_unrecognizedSecurityPolicy = univ.ObjectIdentifier('2.16.840.1.101.2.1.22.3') + + +# Map of Attribute Type OIDs to Attributes added to the +# ones that are in rfc5652.py + +_cmsAttributesMapUpdate = { + id_aa_contentHint: ContentHints(), + id_aa_communityIdentifiers: CommunityIdentifiers(), + id_aa_binarySigningTime: BinarySigningTime(), + id_contentType: ContentType(), + id_messageDigest: MessageDigest(), + id_aa_KP_keyPkgIdAndReceiptReq: KeyPkgIdentifierAndReceiptReq(), + id_aa_KP_keyProvinceV2: KeyProvinceV2(), + id_aa_KP_manifest: Manifest(), + id_kma_keyAlgorithm: KeyAlgorithm(), + id_at_userCertificate: Certificate(), + id_kma_keyPkgReceiversV2: KeyPkgReceiversV2(), + id_kma_TSECNomenclature: TSECNomenclature(), + id_kma_keyPurpose: KeyPurpose(), + id_kma_keyUse: KeyUse(), + id_kma_transportKey: TransOp(), + id_kma_keyDistPeriod: KeyDistPeriod(), + id_kma_keyValidityPeriod: KeyValidityPeriod(), + id_kma_keyDuration: KeyDuration(), + id_aa_KP_classification: Classification(), + id_kma_splitID: SplitID(), + id_kma_keyPkgType: KeyPkgType(), + id_kma_sigUsageV3: SignatureUsage(), + id_kma_otherCertFormats: CertificateChoices(), + id_at_pkiPath: PkiPath(), + id_kma_usefulCerts: CertificateSet(), + id_kma_keyWrapAlgorithm: AlgorithmIdentifier(), + id_aa_KP_contentDecryptKeyID: ContentDecryptKeyID(), + id_pe_subjectInfoAccess: SubjectInfoAccessSyntax(), + id_aa_KP_crlPointers: GeneralNames(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) diff --git a/pyasn1_modules/rfc7914.py b/pyasn1_modules/rfc7914.py new file mode 100644 index 0000000..99e9551 --- /dev/null +++ b/pyasn1_modules/rfc7914.py @@ -0,0 +1,49 @@ +# +# 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 +# +#The scrypt Password-Based Key Derivation Function +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8520.txt +# https://www.rfc-editor.org/errata/eid5871 +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + +MAX = float('inf') + + +id_scrypt = univ.ObjectIdentifier('1.3.6.1.4.1.11591.4.11') + + +class Scrypt_params(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('salt', + univ.OctetString()), + namedtype.NamedType('costParameter', + univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(1, MAX))), + namedtype.NamedType('blockSize', + univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(1, MAX))), + namedtype.NamedType('parallelizationParameter', + univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(1, MAX))), + namedtype.OptionalNamedType('keyLength', + univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(1, MAX))) + ) + + +# Update the Algorithm Identifier map in rfc5280.py + +_algorithmIdentifierMapUpdate = { + id_scrypt: Scrypt_params(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc8017.py b/pyasn1_modules/rfc8017.py new file mode 100644 index 0000000..fefed1d --- /dev/null +++ b/pyasn1_modules/rfc8017.py @@ -0,0 +1,153 @@ +# +# 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 +# +# PKCS #1: RSA Cryptography Specifications Version 2.2 +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8017.txt +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import univ + +from pyasn1_modules import rfc2437 +from pyasn1_modules import rfc3447 +from pyasn1_modules import rfc4055 +from pyasn1_modules import rfc5280 + +MAX = float('inf') + + +# Import Algorithm Identifier from RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + +class DigestAlgorithm(AlgorithmIdentifier): + pass + +class HashAlgorithm(AlgorithmIdentifier): + pass + +class MaskGenAlgorithm(AlgorithmIdentifier): + pass + +class PSourceAlgorithm(AlgorithmIdentifier): + pass + + +# Object identifiers from NIST SHA2 + +hashAlgs = univ.ObjectIdentifier('2.16.840.1.101.3.4.2') +id_sha256 = rfc4055.id_sha256 +id_sha384 = rfc4055.id_sha384 +id_sha512 = rfc4055.id_sha512 +id_sha224 = rfc4055.id_sha224 +id_sha512_224 = hashAlgs + (5, ) +id_sha512_256 = hashAlgs + (6, ) + + +# Basic object identifiers + +pkcs_1 = univ.ObjectIdentifier('1.2.840.113549.1.1') +rsaEncryption = rfc2437.rsaEncryption +id_RSAES_OAEP = rfc2437.id_RSAES_OAEP +id_pSpecified = rfc2437.id_pSpecified +id_RSASSA_PSS = rfc4055.id_RSASSA_PSS +md2WithRSAEncryption = rfc2437.md2WithRSAEncryption +md5WithRSAEncryption = rfc2437.md5WithRSAEncryption +sha1WithRSAEncryption = rfc2437.sha1WithRSAEncryption +sha224WithRSAEncryption = rfc4055.sha224WithRSAEncryption +sha256WithRSAEncryption = rfc4055.sha256WithRSAEncryption +sha384WithRSAEncryption = rfc4055.sha384WithRSAEncryption +sha512WithRSAEncryption = rfc4055.sha512WithRSAEncryption +sha512_224WithRSAEncryption = pkcs_1 + (15, ) +sha512_256WithRSAEncryption = pkcs_1 + (16, ) +id_sha1 = rfc2437.id_sha1 +id_md2 = univ.ObjectIdentifier('1.2.840.113549.2.2') +id_md5 = univ.ObjectIdentifier('1.2.840.113549.2.5') +id_mgf1 = rfc2437.id_mgf1 + + +# Default parameter values + +sha1 = rfc4055.sha1Identifier +SHA1Parameters = univ.Null("") + +mgf1SHA1 = rfc4055.mgf1SHA1Identifier + +class EncodingParameters(univ.OctetString): + subtypeSpec = constraint.ValueSizeConstraint(0, MAX) + +pSpecifiedEmpty = rfc4055.pSpecifiedEmptyIdentifier + +emptyString = EncodingParameters(value='') + + +# Main structures + +class Version(univ.Integer): + namedValues = namedval.NamedValues( + ('two-prime', 0), + ('multi', 1) + ) + +class TrailerField(univ.Integer): + namedValues = namedval.NamedValues( + ('trailerFieldBC', 1) + ) + +RSAPublicKey = rfc2437.RSAPublicKey + +OtherPrimeInfo = rfc3447.OtherPrimeInfo +OtherPrimeInfos = rfc3447.OtherPrimeInfos +RSAPrivateKey = rfc3447.RSAPrivateKey + +RSAES_OAEP_params = rfc4055.RSAES_OAEP_params +rSAES_OAEP_Default_Identifier = rfc4055.rSAES_OAEP_Default_Identifier + +RSASSA_PSS_params = rfc4055.RSASSA_PSS_params +rSASSA_PSS_Default_Identifier = rfc4055.rSASSA_PSS_Default_Identifier + + +# Syntax for the EMSA-PKCS1-v1_5 hash identifier + +class DigestInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('digestAlgorithm', DigestAlgorithm()), + namedtype.NamedType('digest', univ.OctetString()) + ) + + +# Update the Algorithm Identifier map + +_algorithmIdentifierMapUpdate = { + id_sha1: univ.Null(), + id_sha224: univ.Null(), + id_sha256: univ.Null(), + id_sha384: univ.Null(), + id_sha512: univ.Null(), + id_sha512_224: univ.Null(), + id_sha512_256: univ.Null(), + id_mgf1: AlgorithmIdentifier(), + id_pSpecified: univ.OctetString(), + id_RSAES_OAEP: RSAES_OAEP_params(), + id_RSASSA_PSS: RSASSA_PSS_params(), + md2WithRSAEncryption: univ.Null(), + md5WithRSAEncryption: univ.Null(), + sha1WithRSAEncryption: univ.Null(), + sha224WithRSAEncryption: univ.Null(), + sha256WithRSAEncryption: univ.Null(), + sha384WithRSAEncryption: univ.Null(), + sha512WithRSAEncryption: univ.Null(), + sha512_224WithRSAEncryption: univ.Null(), + sha512_256WithRSAEncryption: univ.Null(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc8018.py b/pyasn1_modules/rfc8018.py new file mode 100644 index 0000000..7a44eea --- /dev/null +++ b/pyasn1_modules/rfc8018.py @@ -0,0 +1,260 @@ +# +# 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 +# +# PKCS #5: Password-Based Cryptography Specification, Version 2.1 +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8018.txt +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import univ + +from pyasn1_modules import rfc3565 +from pyasn1_modules import rfc5280 + +MAX = float('inf') + +def _OID(*components): + output = [] + for x in tuple(components): + if isinstance(x, univ.ObjectIdentifier): + output.extend(list(x)) + else: + output.append(int(x)) + + return univ.ObjectIdentifier(output) + + +# Import from RFC 3565 + +AES_IV = rfc3565.AES_IV + + +# Import from RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + + +# Basic object identifiers + +nistAlgorithms = _OID(2, 16, 840, 1, 101, 3, 4) + +aes = _OID(nistAlgorithms, 1) + +oiw = _OID(1, 3, 14) + +rsadsi = _OID(1, 2, 840, 113549) + +pkcs = _OID(rsadsi, 1) + +digestAlgorithm = _OID(rsadsi, 2) + +encryptionAlgorithm = _OID(rsadsi, 3) + +pkcs_5 = _OID(pkcs, 5) + + + +# HMAC object identifiers + +id_hmacWithSHA1 = _OID(digestAlgorithm, 7) + +id_hmacWithSHA224 = _OID(digestAlgorithm, 8) + +id_hmacWithSHA256 = _OID(digestAlgorithm, 9) + +id_hmacWithSHA384 = _OID(digestAlgorithm, 10) + +id_hmacWithSHA512 = _OID(digestAlgorithm, 11) + +id_hmacWithSHA512_224 = _OID(digestAlgorithm, 12) + +id_hmacWithSHA512_256 = _OID(digestAlgorithm, 13) + + +# PBES1 object identifiers + +pbeWithMD2AndDES_CBC = _OID(pkcs_5, 1) + +pbeWithMD2AndRC2_CBC = _OID(pkcs_5, 4) + +pbeWithMD5AndDES_CBC = _OID(pkcs_5, 3) + +pbeWithMD5AndRC2_CBC = _OID(pkcs_5, 6) + +pbeWithSHA1AndDES_CBC = _OID(pkcs_5, 10) + +pbeWithSHA1AndRC2_CBC = _OID(pkcs_5, 11) + + +# Supporting techniques object identifiers + +desCBC = _OID(oiw, 3, 2, 7) + +des_EDE3_CBC = _OID(encryptionAlgorithm, 7) + +rc2CBC = _OID(encryptionAlgorithm, 2) + +rc5_CBC_PAD = _OID(encryptionAlgorithm, 9) + +aes128_CBC_PAD = _OID(aes, 2) + +aes192_CBC_PAD = _OID(aes, 22) + +aes256_CBC_PAD = _OID(aes, 42) + + +# PBES1 + +class PBEParameter(univ.Sequence): + pass + +PBEParameter.componentType = namedtype.NamedTypes( + namedtype.NamedType('salt', univ.OctetString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(8, 8))), + namedtype.NamedType('iterationCount', univ.Integer()) +) + + +# PBES2 + +id_PBES2 = _OID(pkcs_5, 13) + + +class PBES2_params(univ.Sequence): + pass + +PBES2_params.componentType = namedtype.NamedTypes( + namedtype.NamedType('keyDerivationFunc', AlgorithmIdentifier()), + namedtype.NamedType('encryptionScheme', AlgorithmIdentifier()) +) + + +# PBMAC1 + +id_PBMAC1 = _OID(pkcs_5, 14) + + +class PBMAC1_params(univ.Sequence): + pass + +PBMAC1_params.componentType = namedtype.NamedTypes( + namedtype.NamedType('keyDerivationFunc', AlgorithmIdentifier()), + namedtype.NamedType('messageAuthScheme', AlgorithmIdentifier()) +) + + +# PBKDF2 + +id_PBKDF2 = _OID(pkcs_5, 12) + + +algid_hmacWithSHA1 = AlgorithmIdentifier() +algid_hmacWithSHA1['algorithm'] = id_hmacWithSHA1 +algid_hmacWithSHA1['parameters'] = univ.Null("") + + +class PBKDF2_params(univ.Sequence): + pass + +PBKDF2_params.componentType = namedtype.NamedTypes( + namedtype.NamedType('salt', univ.Choice(componentType=namedtype.NamedTypes( + namedtype.NamedType('specified', univ.OctetString()), + namedtype.NamedType('otherSource', AlgorithmIdentifier()) + ))), + namedtype.NamedType('iterationCount', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(1, MAX))), + namedtype.OptionalNamedType('keyLength', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(1, MAX))), + namedtype.DefaultedNamedType('prf', algid_hmacWithSHA1) +) + + +# RC2 CBC algorithm parameter + +class RC2_CBC_Parameter(univ.Sequence): + pass + +RC2_CBC_Parameter.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('rc2ParameterVersion', univ.Integer()), + namedtype.NamedType('iv', univ.OctetString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(8, 8))) +) + + +# RC5 CBC algorithm parameter + +class RC5_CBC_Parameters(univ.Sequence): + pass + +RC5_CBC_Parameters.componentType = namedtype.NamedTypes( + namedtype.NamedType('version', + univ.Integer(namedValues=namedval.NamedValues(('v1_0', 16))).subtype( + subtypeSpec=constraint.SingleValueConstraint(16))), + namedtype.NamedType('rounds', + univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(8, 127))), + namedtype.NamedType('blockSizeInBits', + univ.Integer().subtype(subtypeSpec=constraint.SingleValueConstraint(64, 128))), + namedtype.OptionalNamedType('iv', univ.OctetString()) +) + + +# Initialization Vector for AES: OCTET STRING (SIZE(16)) + +class AES_IV(univ.OctetString): + pass + +AES_IV.subtypeSpec = constraint.ValueSizeConstraint(16, 16) + + +# Initialization Vector for DES: OCTET STRING (SIZE(8)) + +class DES_IV(univ.OctetString): + pass + +DES_IV.subtypeSpec = constraint.ValueSizeConstraint(8, 8) + + +# Update the Algorithm Identifier map + +_algorithmIdentifierMapUpdate = { + # PBKDF2-PRFs + id_hmacWithSHA1: univ.Null(), + id_hmacWithSHA224: univ.Null(), + id_hmacWithSHA256: univ.Null(), + id_hmacWithSHA384: univ.Null(), + id_hmacWithSHA512: univ.Null(), + id_hmacWithSHA512_224: univ.Null(), + id_hmacWithSHA512_256: univ.Null(), + # PBES1Algorithms + pbeWithMD2AndDES_CBC: PBEParameter(), + pbeWithMD2AndRC2_CBC: PBEParameter(), + pbeWithMD5AndDES_CBC: PBEParameter(), + pbeWithMD5AndRC2_CBC: PBEParameter(), + pbeWithSHA1AndDES_CBC: PBEParameter(), + pbeWithSHA1AndRC2_CBC: PBEParameter(), + # PBES2Algorithms + id_PBES2: PBES2_params(), + # PBES2-KDFs + id_PBKDF2: PBKDF2_params(), + # PBMAC1Algorithms + id_PBMAC1: PBMAC1_params(), + # SupportingAlgorithms + desCBC: DES_IV(), + des_EDE3_CBC: DES_IV(), + rc2CBC: RC2_CBC_Parameter(), + rc5_CBC_PAD: RC5_CBC_Parameters(), + aes128_CBC_PAD: AES_IV(), + aes192_CBC_PAD: AES_IV(), + aes256_CBC_PAD: AES_IV(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc8103.py b/pyasn1_modules/rfc8103.py new file mode 100644 index 0000000..6429e86 --- /dev/null +++ b/pyasn1_modules/rfc8103.py @@ -0,0 +1,36 @@ +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley with assistance from the asn1ate tool. +# Auto-generated by asn1ate v.0.6.0 from rfc8103.asn. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# ChaCha20Poly1305 algorithm fo use with the Authenticated-Enveloped-Data +# protecting content type for the Cryptographic Message Syntax (CMS) +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8103.txt + +from pyasn1.type import constraint +from pyasn1.type import univ + + +def _OID(*components): + output = [] + for x in tuple(components): + if isinstance(x, univ.ObjectIdentifier): + output.extend(list(x)) + else: + output.append(int(x)) + + return univ.ObjectIdentifier(output) + + +class AEADChaCha20Poly1305Nonce(univ.OctetString): + pass + + +AEADChaCha20Poly1305Nonce.subtypeSpec = constraint.ValueSizeConstraint(12, 12) + +id_alg_AEADChaCha20Poly1305 = _OID(1, 2, 840, 113549, 1, 9, 16, 3, 18) diff --git a/pyasn1_modules/rfc8209.py b/pyasn1_modules/rfc8209.py new file mode 100644 index 0000000..7d70f51 --- /dev/null +++ b/pyasn1_modules/rfc8209.py @@ -0,0 +1,20 @@ +# +# 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 +# +# BGPsec Router PKI Profile +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8209.txt +# + +from pyasn1.type import univ + + +id_kp = univ.ObjectIdentifier('1.3.6.1.5.5.7.3') + +id_kp_bgpsec_router = id_kp + (30, ) diff --git a/pyasn1_modules/rfc8226.py b/pyasn1_modules/rfc8226.py new file mode 100644 index 0000000..e7fe946 --- /dev/null +++ b/pyasn1_modules/rfc8226.py @@ -0,0 +1,149 @@ +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley with assistance from the asn1ate tool, with manual +# changes to implement appropriate constraints and added comments. +# Modified by Russ Housley to add maps for use with opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# JWT Claim Constraints and TN Authorization List for certificate extensions. +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8226.txt (with errata corrected) + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + +MAX = float('inf') + + +def _OID(*components): + output = [] + for x in tuple(components): + if isinstance(x, univ.ObjectIdentifier): + output.extend(list(x)) + else: + output.append(int(x)) + + return univ.ObjectIdentifier(output) + + +class JWTClaimName(char.IA5String): + pass + + +class JWTClaimNames(univ.SequenceOf): + pass + +JWTClaimNames.componentType = JWTClaimName() +JWTClaimNames.sizeSpec = constraint.ValueSizeConstraint(1, MAX) + + +class JWTClaimPermittedValues(univ.Sequence): + pass + +JWTClaimPermittedValues.componentType = namedtype.NamedTypes( + namedtype.NamedType('claim', JWTClaimName()), + namedtype.NamedType('permitted', univ.SequenceOf( + componentType=char.UTF8String()).subtype( + sizeSpec=constraint.ValueSizeConstraint(1, MAX))) +) + + +class JWTClaimPermittedValuesList(univ.SequenceOf): + pass + +JWTClaimPermittedValuesList.componentType = JWTClaimPermittedValues() +JWTClaimPermittedValuesList.sizeSpec = constraint.ValueSizeConstraint(1, MAX) + + +class JWTClaimConstraints(univ.Sequence): + pass + +JWTClaimConstraints.componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('mustInclude', + JWTClaimNames().subtype(explicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('permittedValues', + JWTClaimPermittedValuesList().subtype(explicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 1))) +) + +JWTClaimConstraints.subtypeSpec = constraint.ConstraintsUnion( + constraint.WithComponentsConstraint( + ('mustInclude', constraint.ComponentPresentConstraint())), + constraint.WithComponentsConstraint( + ('permittedValues', constraint.ComponentPresentConstraint())) +) + + +id_pe_JWTClaimConstraints = _OID(1, 3, 6, 1, 5, 5, 7, 1, 27) + + +class ServiceProviderCode(char.IA5String): + pass + + +class TelephoneNumber(char.IA5String): + pass + +TelephoneNumber.subtypeSpec = constraint.ConstraintsIntersection( + constraint.ValueSizeConstraint(1, 15), + constraint.PermittedAlphabetConstraint( + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#', '*') +) + + +class TelephoneNumberRange(univ.Sequence): + pass + +TelephoneNumberRange.componentType = namedtype.NamedTypes( + namedtype.NamedType('start', TelephoneNumber()), + namedtype.NamedType('count', + univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(2, MAX))) +) + + +class TNEntry(univ.Choice): + pass + +TNEntry.componentType = namedtype.NamedTypes( + namedtype.NamedType('spc', + ServiceProviderCode().subtype(explicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 0))), + namedtype.NamedType('range', + TelephoneNumberRange().subtype(explicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatConstructed, 1))), + namedtype.NamedType('one', + TelephoneNumber().subtype(explicitTag=tag.Tag(tag.tagClassContext, + tag.tagFormatSimple, 2))) +) + + +class TNAuthorizationList(univ.SequenceOf): + pass + +TNAuthorizationList.componentType = TNEntry() +TNAuthorizationList.sizeSpec = constraint.ValueSizeConstraint(1, MAX) + +id_pe_TNAuthList = _OID(1, 3, 6, 1, 5, 5, 7, 1, 26) + + +id_ad_stirTNList = _OID(1, 3, 6, 1, 5, 5, 7, 48, 14) + + +# Map of Certificate Extension OIDs to Extensions added to the +# ones that are in rfc5280.py + +_certificateExtensionsMapUpdate = { + id_pe_TNAuthList: TNAuthorizationList(), + id_pe_JWTClaimConstraints: JWTClaimConstraints(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMapUpdate) diff --git a/pyasn1_modules/rfc8358.py b/pyasn1_modules/rfc8358.py new file mode 100644 index 0000000..647a366 --- /dev/null +++ b/pyasn1_modules/rfc8358.py @@ -0,0 +1,50 @@ +# +# 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 +# +# Digital Signatures on Internet-Draft Documents +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8358.txt +# + +from pyasn1.type import univ + +from pyasn1_modules import rfc5652 + + +id_ct = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1') + +id_ct_asciiTextWithCRLF = id_ct + (27, ) + +id_ct_epub = id_ct + (39, ) + +id_ct_htmlWithCRLF = id_ct + (38, ) + +id_ct_pdf = id_ct + (29, ) + +id_ct_postscript = id_ct + (30, ) + +id_ct_utf8TextWithCRLF = id_ct + (37, ) + +id_ct_xml = id_ct + (28, ) + + +# Map of Content Type OIDs to Content Types is added to the +# ones that are in rfc5652.py + +_cmsContentTypesMapUpdate = { + id_ct_asciiTextWithCRLF: univ.OctetString(), + id_ct_epub: univ.OctetString(), + id_ct_htmlWithCRLF: univ.OctetString(), + id_ct_pdf: univ.OctetString(), + id_ct_postscript: univ.OctetString(), + id_ct_utf8TextWithCRLF: univ.OctetString(), + id_ct_xml: univ.OctetString(), +} + +rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate) diff --git a/pyasn1_modules/rfc8360.py b/pyasn1_modules/rfc8360.py new file mode 100644 index 0000000..ca180c1 --- /dev/null +++ b/pyasn1_modules/rfc8360.py @@ -0,0 +1,44 @@ +# +# 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 +# +# Resource Public Key Infrastructure (RPKI) Validation Reconsidered +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8360.txt +# https://www.rfc-editor.org/errata/eid5870 +# + +from pyasn1.type import univ + +from pyasn1_modules import rfc3779 +from pyasn1_modules import rfc5280 + + +# IP Address Delegation Extension V2 + +id_pe_ipAddrBlocks_v2 = univ.ObjectIdentifier('1.3.6.1.5.5.7.1.28') + +IPAddrBlocks = rfc3779.IPAddrBlocks + + +# Autonomous System Identifier Delegation Extension V2 + +id_pe_autonomousSysIds_v2 = univ.ObjectIdentifier('1.3.6.1.5.5.7.1.29') + +ASIdentifiers = rfc3779.ASIdentifiers + + +# Map of Certificate Extension OIDs to Extensions is added to the +# ones that are in rfc5280.py + +_certificateExtensionsMapUpdate = { + id_pe_ipAddrBlocks_v2: IPAddrBlocks(), + id_pe_autonomousSysIds_v2: ASIdentifiers(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMapUpdate) diff --git a/pyasn1_modules/rfc8398.py b/pyasn1_modules/rfc8398.py new file mode 100644 index 0000000..151b632 --- /dev/null +++ b/pyasn1_modules/rfc8398.py @@ -0,0 +1,52 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with some assistance from asn1ate v.0.6.0. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Internationalized Email Addresses in X.509 Certificates +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8398.txt +# https://www.rfc-editor.org/errata/eid5418 +# + +from pyasn1.type import char +from pyasn1.type import constraint +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + +MAX = float('inf') + + +# SmtpUTF8Mailbox contains Mailbox as specified in Section 3.3 of RFC 6531 + +id_pkix = rfc5280.id_pkix + +id_on = id_pkix + (8, ) + +id_on_SmtpUTF8Mailbox = id_on + (9, ) + + +class SmtpUTF8Mailbox(char.UTF8String): + pass + +SmtpUTF8Mailbox.subtypeSpec = constraint.ValueSizeConstraint(1, MAX) + + +on_SmtpUTF8Mailbox = rfc5280.AnotherName() +on_SmtpUTF8Mailbox['type-id'] = id_on_SmtpUTF8Mailbox +on_SmtpUTF8Mailbox['value'] = SmtpUTF8Mailbox() + + +# Map of Other Name OIDs to Other Name is added to the +# ones that are in rfc5280.py + +_anotherNameMapUpdate = { + id_on_SmtpUTF8Mailbox: SmtpUTF8Mailbox(), +} + +rfc5280.anotherNameMap.update(_anotherNameMapUpdate) diff --git a/pyasn1_modules/rfc8410.py b/pyasn1_modules/rfc8410.py new file mode 100644 index 0000000..98bc97b --- /dev/null +++ b/pyasn1_modules/rfc8410.py @@ -0,0 +1,43 @@ +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Algorithm Identifiers for Ed25519, Ed448, X25519, and X448 +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8410.txt + +from pyasn1.type import univ +from pyasn1_modules import rfc3565 +from pyasn1_modules import rfc4055 +from pyasn1_modules import rfc5280 + + +class SignatureAlgorithmIdentifier(rfc5280.AlgorithmIdentifier): + pass + + +class KeyEncryptionAlgorithmIdentifier(rfc5280.AlgorithmIdentifier): + pass + + +class CurvePrivateKey(univ.OctetString): + pass + + +id_X25519 = univ.ObjectIdentifier('1.3.101.110') + +id_X448 = univ.ObjectIdentifier('1.3.101.111') + +id_Ed25519 = univ.ObjectIdentifier('1.3.101.112') + +id_Ed448 = univ.ObjectIdentifier('1.3.101.113') + +id_sha512 = rfc4055.id_sha512 + +id_aes128_wrap = rfc3565.id_aes128_wrap + +id_aes256_wrap = rfc3565.id_aes256_wrap diff --git a/pyasn1_modules/rfc8418.py b/pyasn1_modules/rfc8418.py new file mode 100644 index 0000000..6e76487 --- /dev/null +++ b/pyasn1_modules/rfc8418.py @@ -0,0 +1,36 @@ +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Elliptic Curve Diffie-Hellman (ECDH) Key Agreement Algorithm +# with X25519 and X448 +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8418.txt + +from pyasn1.type import univ +from pyasn1_modules import rfc5280 + + +class KeyEncryptionAlgorithmIdentifier(rfc5280.AlgorithmIdentifier): + pass + + +class KeyWrapAlgorithmIdentifier(rfc5280.AlgorithmIdentifier): + pass + + +dhSinglePass_stdDH_sha256kdf_scheme = univ.ObjectIdentifier('1.3.133.16.840.63.0.11.1') + +dhSinglePass_stdDH_sha384kdf_scheme = univ.ObjectIdentifier('1.3.133.16.840.63.0.11.2') + +dhSinglePass_stdDH_sha512kdf_scheme = univ.ObjectIdentifier('1.3.133.16.840.63.0.11.3') + +dhSinglePass_stdDH_hkdf_sha256_scheme = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.19') + +dhSinglePass_stdDH_hkdf_sha384_scheme = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.20') + +dhSinglePass_stdDH_hkdf_sha512_scheme = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.21') diff --git a/pyasn1_modules/rfc8419.py b/pyasn1_modules/rfc8419.py new file mode 100644 index 0000000..f10994b --- /dev/null +++ b/pyasn1_modules/rfc8419.py @@ -0,0 +1,68 @@ +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Edwards-Curve Digital Signature Algorithm (EdDSA) Signatures in the CMS +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8419.txt +# https://www.rfc-editor.org/errata/eid5869 + + +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +class ShakeOutputLen(univ.Integer): + pass + + +id_Ed25519 = univ.ObjectIdentifier('1.3.101.112') + +sigAlg_Ed25519 = rfc5280.AlgorithmIdentifier() +sigAlg_Ed25519['algorithm'] = id_Ed25519 +# sigAlg_Ed25519['parameters'] is absent + + +id_Ed448 = univ.ObjectIdentifier('1.3.101.113') + +sigAlg_Ed448 = rfc5280.AlgorithmIdentifier() +sigAlg_Ed448['algorithm'] = id_Ed448 +# sigAlg_Ed448['parameters'] is absent + + +hashAlgs = univ.ObjectIdentifier('2.16.840.1.101.3.4.2') + +id_sha512 = hashAlgs + (3, ) + +hashAlg_SHA_512 = rfc5280.AlgorithmIdentifier() +hashAlg_SHA_512['algorithm'] = id_sha512 +# hashAlg_SHA_512['parameters'] is absent + + +id_shake256 = hashAlgs + (12, ) + +hashAlg_SHAKE256 = rfc5280.AlgorithmIdentifier() +hashAlg_SHAKE256['algorithm'] = id_shake256 +# hashAlg_SHAKE256['parameters']is absent + + +id_shake256_len = hashAlgs + (18, ) + +hashAlg_SHAKE256_LEN = rfc5280.AlgorithmIdentifier() +hashAlg_SHAKE256_LEN['algorithm'] = id_shake256_len +hashAlg_SHAKE256_LEN['parameters'] = ShakeOutputLen() + + +# Map of Algorithm Identifier OIDs to Parameters added to the +# ones in rfc5280.py. Do not add OIDs with absent paramaters. + +_algorithmIdentifierMapUpdate = { + id_shake256_len: ShakeOutputLen(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc8479.py b/pyasn1_modules/rfc8479.py new file mode 100644 index 0000000..57f78b6 --- /dev/null +++ b/pyasn1_modules/rfc8479.py @@ -0,0 +1,45 @@ +# +# 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 +# +# Storing Validation Parameters in PKCS#8 +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8479.txt +# + +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5652 + + +id_attr_validation_parameters = univ.ObjectIdentifier('1.3.6.1.4.1.2312.18.8.1') + + +class ValidationParams(univ.Sequence): + pass + +ValidationParams.componentType = namedtype.NamedTypes( + namedtype.NamedType('hashAlg', univ.ObjectIdentifier()), + namedtype.NamedType('seed', univ.OctetString()) +) + + +at_validation_parameters = rfc5652.Attribute() +at_validation_parameters['attrType'] = id_attr_validation_parameters +at_validation_parameters['attrValues'][0] = ValidationParams() + + +# Map of Attribute Type OIDs to Attributes added to the +# ones that are in rfc5652.py + +_cmsAttributesMapUpdate = { + id_attr_validation_parameters: ValidationParams(), +} + +rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate) diff --git a/pyasn1_modules/rfc8494.py b/pyasn1_modules/rfc8494.py new file mode 100644 index 0000000..fe349e1 --- /dev/null +++ b/pyasn1_modules/rfc8494.py @@ -0,0 +1,80 @@ +# This file is being contributed to 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 +# +# Multicast Email (MULE) over Allied Communications Publication 142 +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8494.txt + +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import tag +from pyasn1.type import univ + + +id_mmhs_CDT = univ.ObjectIdentifier('1.3.26.0.4406.0.4.2') + + +class AlgorithmID_ShortForm(univ.Integer): + pass + +AlgorithmID_ShortForm.namedValues = namedval.NamedValues( + ('zlibCompress', 0) +) + + +class ContentType_ShortForm(univ.Integer): + pass + +ContentType_ShortForm.namedValues = namedval.NamedValues( + ('unidentified', 0), + ('external', 1), + ('p1', 2), + ('p3', 3), + ('p7', 4), + ('mule', 25) +) + + +class CompressedContentInfo(univ.Sequence): + pass + +CompressedContentInfo.componentType = namedtype.NamedTypes( + namedtype.NamedType('unnamed', univ.Choice(componentType=namedtype.NamedTypes( + namedtype.NamedType('contentType-ShortForm', + ContentType_ShortForm().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('contentType-OID', + univ.ObjectIdentifier().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))) + ))), + namedtype.NamedType('compressedContent', + univ.OctetString().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))) +) + + +class CompressionAlgorithmIdentifier(univ.Choice): + pass + +CompressionAlgorithmIdentifier.componentType = namedtype.NamedTypes( + namedtype.NamedType('algorithmID-ShortForm', + AlgorithmID_ShortForm().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.NamedType('algorithmID-OID', + univ.ObjectIdentifier().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))) +) + + +class CompressedData(univ.Sequence): + pass + +CompressedData.componentType = namedtype.NamedTypes( + namedtype.NamedType('compressionAlgorithm', CompressionAlgorithmIdentifier()), + namedtype.NamedType('compressedContentInfo', CompressedContentInfo()) +) diff --git a/pyasn1_modules/rfc8520.py b/pyasn1_modules/rfc8520.py new file mode 100644 index 0000000..b9eb6e9 --- /dev/null +++ b/pyasn1_modules/rfc8520.py @@ -0,0 +1,63 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with assistance from asn1ate v.0.6.0. +# Modified by Russ Housley to add maps for use with opentypes. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# X.509 Extensions for MUD URL and MUD Signer; +# Object Identifier for CMS Content Type for a MUD file +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8520.txt +# + +from pyasn1.type import char +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 + + +# X.509 Extension for MUD URL + +id_pe_mud_url = univ.ObjectIdentifier('1.3.6.1.5.5.7.1.25') + +class MUDURLSyntax(char.IA5String): + pass + + +# X.509 Extension for MUD Signer + +id_pe_mudsigner = univ.ObjectIdentifier('1.3.6.1.5.5.7.1.30') + +class MUDsignerSyntax(rfc5280.Name): + pass + + +# Object Identifier for CMS Content Type for a MUD file + +id_ct_mudtype = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.41') + + +# Map of Certificate Extension OIDs to Extensions added to the +# ones that are in rfc5280.py + +_certificateExtensionsMapUpdate = { + id_pe_mud_url: MUDURLSyntax(), + id_pe_mudsigner: MUDsignerSyntax(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMapUpdate) + + +# Map of Content Type OIDs to Content Types added to the +# ones that are in rfc5652.py + +_cmsContentTypesMapUpdate = { + id_ct_mudtype: univ.OctetString(), +} + +rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate) diff --git a/pyasn1_modules/rfc8619.py b/pyasn1_modules/rfc8619.py new file mode 100644 index 0000000..0aaa811 --- /dev/null +++ b/pyasn1_modules/rfc8619.py @@ -0,0 +1,45 @@ +# +# 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 +# +# Algorithm Identifiers for HKDF +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8619.txt +# + +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +# Object Identifiers + +id_alg_hkdf_with_sha256 = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.28') + + +id_alg_hkdf_with_sha384 = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.29') + + +id_alg_hkdf_with_sha512 = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.30') + + +# Key Derivation Algorithm Identifiers + +kda_hkdf_with_sha256 = rfc5280.AlgorithmIdentifier() +kda_hkdf_with_sha256['algorithm'] = id_alg_hkdf_with_sha256 +# kda_hkdf_with_sha256['parameters'] are absent + + +kda_hkdf_with_sha384 = rfc5280.AlgorithmIdentifier() +kda_hkdf_with_sha384['algorithm'] = id_alg_hkdf_with_sha384 +# kda_hkdf_with_sha384['parameters'] are absent + + +kda_hkdf_with_sha512 = rfc5280.AlgorithmIdentifier() +kda_hkdf_with_sha512['algorithm'] = id_alg_hkdf_with_sha512 +# kda_hkdf_with_sha512['parameters'] are absent diff --git a/pyasn1_modules/rfc8649.py b/pyasn1_modules/rfc8649.py new file mode 100644 index 0000000..c405f05 --- /dev/null +++ b/pyasn1_modules/rfc8649.py @@ -0,0 +1,40 @@ +# +# 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 +# +# X.509 Certificate Extension for Hash Of Root Key +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8649.txt +# + +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +id_ce_hashOfRootKey = univ.ObjectIdentifier('1.3.6.1.4.1.51483.2.1') + + +class HashedRootKey(univ.Sequence): + pass + +HashedRootKey.componentType = namedtype.NamedTypes( + namedtype.NamedType('hashAlg', rfc5280.AlgorithmIdentifier()), + namedtype.NamedType('hashValue', univ.OctetString()) +) + + +# Map of Certificate Extension OIDs to Extensions added to the +# ones that are in rfc5280.py + +_certificateExtensionsMapUpdate = { + id_ce_hashOfRootKey: HashedRootKey(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMapUpdate) diff --git a/pyasn1_modules/rfc8692.py b/pyasn1_modules/rfc8692.py new file mode 100644 index 0000000..7a6791a --- /dev/null +++ b/pyasn1_modules/rfc8692.py @@ -0,0 +1,79 @@ +# +# 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 +# +# Algorithm Identifiers for RSASSA-PSS and ECDSA using SHAKEs +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8692.txt +# + +from pyasn1.type import univ + +from pyasn1_modules import rfc4055 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5480 + + +# SHAKE128 One-Way Hash Function + +id_shake128 = univ.ObjectIdentifier('2.16.840.1.101.3.4.2.11') + +mda_shake128 = rfc5280.AlgorithmIdentifier() +mda_shake128['algorithm'] = id_shake128 +# mda_shake128['parameters'] is absent + + +# SHAKE256 One-Way Hash Function + +id_shake256 = univ.ObjectIdentifier('2.16.840.1.101.3.4.2.12') + +mda_shake256 = rfc5280.AlgorithmIdentifier() +mda_shake256['algorithm'] = id_shake256 +# mda_shake256['parameters'] is absent + + +# RSA PSS with SHAKE128 + +id_RSASSA_PSS_SHAKE128 = univ.ObjectIdentifier('1.3.6.1.5.5.7.6.30') + +sa_rSASSA_PSS_SHAKE128 = rfc5280.AlgorithmIdentifier() +sa_rSASSA_PSS_SHAKE128['algorithm'] = id_RSASSA_PSS_SHAKE128 +# sa_rSASSA_PSS_SHAKE128['parameters'] is absent + +pk_rsaSSA_PSS_SHAKE128 = rfc4055.RSAPublicKey() + + +# RSA PSS with SHAKE256 + +id_RSASSA_PSS_SHAKE256 = univ.ObjectIdentifier('1.3.6.1.5.5.7.6.31') + +sa_rSASSA_PSS_SHAKE256 = rfc5280.AlgorithmIdentifier() +sa_rSASSA_PSS_SHAKE256['algorithm'] = id_RSASSA_PSS_SHAKE256 +# sa_rSASSA_PSS_SHAKE256['parameters'] is absent + +pk_rsaSSA_PSS_SHAKE256 = rfc4055.RSAPublicKey() + + +# ECDSA with SHAKE128 + +id_ecdsa_with_shake128 = univ.ObjectIdentifier('1.3.6.1.5.5.7.6.32') + +sa_ecdsa_with_shake128 = rfc5280.AlgorithmIdentifier() +sa_ecdsa_with_shake128['algorithm'] = id_ecdsa_with_shake128 +# sa_ecdsa_with_shake128['parameters'] is absent + +pk_ec = rfc5480.ECPoint() + + +# ECDSA with SHAKE128 + +id_ecdsa_with_shake256 = univ.ObjectIdentifier('1.3.6.1.5.5.7.6.33') + +sa_ecdsa_with_shake256 = rfc5280.AlgorithmIdentifier() +sa_ecdsa_with_shake256['algorithm'] = id_ecdsa_with_shake256 +# sa_ecdsa_with_shake256['parameters'] is absent diff --git a/pyasn1_modules/rfc8696.py b/pyasn1_modules/rfc8696.py new file mode 100644 index 0000000..4c6d38d --- /dev/null +++ b/pyasn1_modules/rfc8696.py @@ -0,0 +1,104 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with some assistance from asn1ate v.0.6.0. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# Using Pre-Shared Key (PSK) in the Cryptographic Message Syntax (CMS) +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8696.txt +# + +from pyasn1.type import constraint +from pyasn1.type import namedtype +from pyasn1.type import namedval +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5652 + +MAX = float('inf') + + +id_ori = univ.ObjectIdentifier('1.2.840.113549.1.9.16.13') + +id_ori_keyTransPSK = univ.ObjectIdentifier('1.2.840.113549.1.9.16.13.1') + +id_ori_keyAgreePSK = univ.ObjectIdentifier('1.2.840.113549.1.9.16.13.2') + + +class PreSharedKeyIdentifier(univ.OctetString): + pass + + +class KeyTransRecipientInfos(univ.SequenceOf): + componentType = rfc5652.KeyTransRecipientInfo() + + +class KeyTransPSKRecipientInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('version', + rfc5652.CMSVersion()), + namedtype.NamedType('pskid', + PreSharedKeyIdentifier()), + namedtype.NamedType('kdfAlgorithm', + rfc5652.KeyDerivationAlgorithmIdentifier()), + namedtype.NamedType('keyEncryptionAlgorithm', + rfc5652.KeyEncryptionAlgorithmIdentifier()), + namedtype.NamedType('ktris', + KeyTransRecipientInfos()), + namedtype.NamedType('encryptedKey', + rfc5652.EncryptedKey()) + ) + + +class KeyAgreePSKRecipientInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('version', + rfc5652.CMSVersion()), + namedtype.NamedType('pskid', + PreSharedKeyIdentifier()), + namedtype.NamedType('originator', + rfc5652.OriginatorIdentifierOrKey().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatConstructed, 0))), + namedtype.OptionalNamedType('ukm', + rfc5652.UserKeyingMaterial().subtype(explicitTag=tag.Tag( + tag.tagClassContext, tag.tagFormatSimple, 1))), + namedtype.NamedType('kdfAlgorithm', + rfc5652.KeyDerivationAlgorithmIdentifier()), + namedtype.NamedType('keyEncryptionAlgorithm', + rfc5652.KeyEncryptionAlgorithmIdentifier()), + namedtype.NamedType('recipientEncryptedKeys', + rfc5652.RecipientEncryptedKeys()) + ) + + +class CMSORIforPSKOtherInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('psk', + univ.OctetString()), + namedtype.NamedType('keyMgmtAlgType', + univ.Enumerated(namedValues=namedval.NamedValues( + ('keyTrans', 5), ('keyAgree', 10)))), + namedtype.NamedType('keyEncryptionAlgorithm', + rfc5652.KeyEncryptionAlgorithmIdentifier()), + namedtype.NamedType('pskLength', + univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(1, MAX))), + namedtype.NamedType('kdkLength', + univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(1, MAX))) + ) + + +# Update the CMS Other Recipient Info map in rfc5652.py + +_otherRecipientInfoMapUpdate = { + id_ori_keyTransPSK: KeyTransPSKRecipientInfo(), + id_ori_keyAgreePSK: KeyAgreePSKRecipientInfo(), +} + +rfc5652.otherRecipientInfoMap.update(_otherRecipientInfoMapUpdate) diff --git a/pyasn1_modules/rfc8702.py b/pyasn1_modules/rfc8702.py new file mode 100644 index 0000000..977c278 --- /dev/null +++ b/pyasn1_modules/rfc8702.py @@ -0,0 +1,105 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley with assistance from asn1ate v.0.6.0. +# +# Copyright (c) 2020, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# SHAKE One-way Hash Functions for CMS +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8702.txt +# +from pyasn1.type import namedtype +from pyasn1.type import tag +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc8692 + + +# Imports fprm RFC 5280 + +AlgorithmIdentifier = rfc5280.AlgorithmIdentifier + + +# Imports from RFC 8692 + +id_shake128 = rfc8692.id_shake128 + +mda_shake128 = rfc8692.mda_shake128 + +id_shake256 = rfc8692.id_shake256 + +mda_shake256 = rfc8692.mda_shake256 + +id_RSASSA_PSS_SHAKE128 = rfc8692.id_RSASSA_PSS_SHAKE128 + +sa_rSASSA_PSS_SHAKE128 = rfc8692.sa_rSASSA_PSS_SHAKE128 + +pk_rsaSSA_PSS_SHAKE128 = rfc8692.pk_rsaSSA_PSS_SHAKE128 + +id_RSASSA_PSS_SHAKE256 = rfc8692.id_RSASSA_PSS_SHAKE256 + +sa_rSASSA_PSS_SHAKE256 = rfc8692.sa_rSASSA_PSS_SHAKE256 + +pk_rsaSSA_PSS_SHAKE256 = rfc8692.pk_rsaSSA_PSS_SHAKE256 + +id_ecdsa_with_shake128 = rfc8692.id_ecdsa_with_shake128 + +sa_ecdsa_with_shake128 = rfc8692.sa_ecdsa_with_shake128 + +id_ecdsa_with_shake256 = rfc8692.id_ecdsa_with_shake256 + +sa_ecdsa_with_shake256 = rfc8692.sa_ecdsa_with_shake256 + +pk_ec = rfc8692.pk_ec + + +# KMAC with SHAKE128 + +id_KMACWithSHAKE128 = univ.ObjectIdentifier('2.16.840.1.101.3.4.2.19') + + +class KMACwithSHAKE128_params(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('kMACOutputLength', + univ.Integer().subtype(value=256)), + namedtype.DefaultedNamedType('customizationString', + univ.OctetString().subtype(value='')) + ) + + +maca_KMACwithSHAKE128 = AlgorithmIdentifier() +maca_KMACwithSHAKE128['algorithm'] = id_KMACWithSHAKE128 +maca_KMACwithSHAKE128['parameters'] = KMACwithSHAKE128_params() + + +# KMAC with SHAKE256 + +id_KMACWithSHAKE256 = univ.ObjectIdentifier('2.16.840.1.101.3.4.2.20') + + +class KMACwithSHAKE256_params(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.DefaultedNamedType('kMACOutputLength', + univ.Integer().subtype(value=512)), + namedtype.DefaultedNamedType('customizationString', + univ.OctetString().subtype(value='')) + ) + + +maca_KMACwithSHAKE256 = AlgorithmIdentifier() +maca_KMACwithSHAKE256['algorithm'] = id_KMACWithSHAKE256 +maca_KMACwithSHAKE256['parameters'] = KMACwithSHAKE256_params() + + +# Update the Algorithm Identifier map in rfc5280.py + +_algorithmIdentifierMapUpdate = { + id_KMACWithSHAKE128: KMACwithSHAKE128_params(), + id_KMACWithSHAKE256: KMACwithSHAKE256_params(), +} + +rfc5280.algorithmIdentifierMap.update(_algorithmIdentifierMapUpdate) diff --git a/pyasn1_modules/rfc8708.py b/pyasn1_modules/rfc8708.py new file mode 100644 index 0000000..3e9909c --- /dev/null +++ b/pyasn1_modules/rfc8708.py @@ -0,0 +1,41 @@ +# This file is being contributed to pyasn1-modules software. +# +# Created by Russ Housley +# +# Copyright (c) 2020, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# HSS/LMS Hash-based Signature Algorithm for CMS +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8708.txt + + +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + + +# Object Identifiers + +id_alg_hss_lms_hashsig = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.17') + +id_alg_mts_hashsig = id_alg_hss_lms_hashsig + + +# Signature Algorithm Identifier + +sa_HSS_LMS_HashSig = rfc5280.AlgorithmIdentifier() +sa_HSS_LMS_HashSig['algorithm'] = id_alg_hss_lms_hashsig +# sa_HSS_LMS_HashSig['parameters'] is alway absent + + +# Public Key + +class HSS_LMS_HashSig_PublicKey(univ.OctetString): + pass + + +pk_HSS_LMS_HashSig = rfc5280.SubjectPublicKeyInfo() +pk_HSS_LMS_HashSig['algorithm'] = sa_HSS_LMS_HashSig +# pk_HSS_LMS_HashSig['parameters'] CONTAINS a DER-encoded HSS_LMS_HashSig_PublicKey diff --git a/pyasn1_modules/rfc8769.py b/pyasn1_modules/rfc8769.py new file mode 100644 index 0000000..5d2b300 --- /dev/null +++ b/pyasn1_modules/rfc8769.py @@ -0,0 +1,21 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley. +# +# Copyright (c) 2020, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +# CBOR Content for CMS +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc8769.txt +# + +from pyasn1.type import univ + + +id_ct_cbor = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.44') + + +id_ct_cborSequence = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.45') diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..e3d7c96 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,5 @@ +[build-system] +requires = [ + "setuptools" +] +build-backend = "setuptools.build_meta" diff --git a/requirements.txt b/requirements.txt index 2c51a6a..5ec9d47 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -pyasn1>=0.4.1,<0.5.0 +pyasn1>=0.4.7,<0.7.0 diff --git a/setup.cfg b/setup.cfg index 6f08d0e..e5db9d0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,8 +1,49 @@ -[bdist_wheel] -universal = 1 - -[egg_info] -tag_build = -tag_date = 0 -tag_svn_revision = 0 +[metadata] +name = pyasn1_modules +version = attr: pyasn1_modules.__version__ +description = A collection of ASN.1-based protocols modules +long_description = file: README.md +long_description_content_type = text/markdown +license = BSD +license_file = LICENSE.txt +url = https://github.com/pyasn1/pyasn1-modules +author = Ilya Etingof +author_email = etingof@gmail.com +maintainer = pyasn1 maintenance organization +maintainer_email = Christian Heimes +project_urls = + Source=https://github.com/pyasn1/pyasn1-modules + Issues=https://github.com/pyasn1/pyasn1-modules/issues + Changelog=https://github.com/pyasn1/pyasn1-modules/blob/master/CHANGES.txt +platforms = any +classifiers = + Development Status :: 5 - Production/Stable + Environment :: Console + Intended Audience :: Developers + Intended Audience :: Education + Intended Audience :: Information Technology + Intended Audience :: System Administrators + Intended Audience :: Telecommunications Industry + License :: OSI Approved :: BSD License + Natural Language :: English + Operating System :: OS Independent + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 + Programming Language :: Python :: 3.13 + Programming Language :: Python :: Implementation :: CPython + Programming Language :: Python :: Implementation :: PyPy + Topic :: Communications + Topic :: Software Development :: Libraries :: Python Modules +[options] +python_requires = >=3.8 +zip_safe = True +setup_requires = setuptools +install_requires = + pyasn1>=0.4.6,<0.7.0 +packages = + pyasn1_modules diff --git a/setup.py b/setup.py index 378a851..d7b3b23 100644 --- a/setup.py +++ b/setup.py @@ -2,134 +2,9 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # -import sys +from setuptools import setup -doclines = """A collection of ASN.1-based protocols modules. - - A collection of ASN.1 modules expressed in form of pyasn1 classes. - Includes protocols PDUs definition (SNMP, LDAP etc.) and various - data structures (X.509, PKCS etc.). -""" - -doclines = [x.strip() for x in doclines.split('\n') if x] - - -classifiers = """\ -Development Status :: 5 - Production/Stable -Environment :: Console -Intended Audience :: Developers -Intended Audience :: Education -Intended Audience :: Information Technology -Intended Audience :: System Administrators -Intended Audience :: Telecommunications Industry -License :: OSI Approved :: BSD License -Natural Language :: English -Operating System :: OS Independent -Programming Language :: Python :: 2 -Programming Language :: Python :: 2.4 -Programming Language :: Python :: 2.5 -Programming Language :: Python :: 2.6 -Programming Language :: Python :: 2.7 -Programming Language :: Python :: 3 -Programming Language :: Python :: 3.2 -Programming Language :: Python :: 3.3 -Programming Language :: Python :: 3.4 -Programming Language :: Python :: 3.5 -Programming Language :: Python :: 3.6 -Topic :: Communications -Topic :: System :: Monitoring -Topic :: System :: Networking :: Monitoring -Topic :: Software Development :: Libraries :: Python Modules -""" - - -def howto_install_setuptools(): - print(""" - Error: You need setuptools Python package! - - It's very easy to install it, just type (as root on Linux): - - wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py - python ez_setup.py - - Then you could make eggs from this package. -""") - - -if sys.version_info[:2] < (2, 4): - print("ERROR: this package requires Python 2.4 or later!") - sys.exit(1) - -try: - from setuptools import setup, Command - - params = { - 'zip_safe': True, - 'install_requires': ['pyasn1>=0.4.1,<0.5.0'] - } - -except ImportError: - for arg in sys.argv: - if 'egg' in arg: - howto_install_setuptools() - sys.exit(1) - - from distutils.core import setup, Command - - if sys.version_info[:2] > (2, 4): - params = { - 'requires': ['pyasn1(>=0.4.1,<0.5.0)'] - } - else: - params = { - 'requires': ['pyasn1'] - } - -params.update( - {'name': 'pyasn1-modules', - 'version': open('pyasn1_modules/__init__.py').read().split('\'')[1], - 'description': doclines[0], - 'long_description': ' '.join(doclines[1:]), - 'maintainer': 'Ilya Etingof ', - 'author': 'Ilya Etingof', - 'author_email': 'etingof@gmail.com', - 'url': 'https://github.com/etingof/pyasn1-modules', - 'platforms': ['any'], - 'classifiers': [x for x in classifiers.split('\n') if x], - 'license': 'BSD', - 'packages': ['pyasn1_modules']} -) - - -# handle unittest discovery feature -try: - import unittest2 as unittest -except ImportError: - import unittest - - -class PyTest(Command): - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - suite = unittest.TestLoader().loadTestsFromNames( - ['tests.__main__.suite'] - ) - - unittest.TextTestRunner(verbosity=2).run(suite) - -params['cmdclass'] = { - 'test': PyTest, - 'tests': PyTest -} - -setup(**params) +setup() diff --git a/tests/__main__.py b/tests/__main__.py index c6377a6..4e10bc8 100644 --- a/tests/__main__.py +++ b/tests/__main__.py @@ -1,28 +1,138 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # -try: - import unittest2 as unittest - -except ImportError: - import unittest +import unittest suite = unittest.TestLoader().loadTestsFromNames( - ['tests.test_rfc2314.suite', + ['tests.test_pem.suite', + 'tests.test_rfc2314.suite', 'tests.test_rfc2315.suite', 'tests.test_rfc2437.suite', 'tests.test_rfc2459.suite', 'tests.test_rfc2511.suite', 'tests.test_rfc2560.suite', + 'tests.test_rfc2631.suite', + 'tests.test_rfc2634.suite', + 'tests.test_rfc2876.suite', + 'tests.test_rfc2985.suite', + 'tests.test_rfc2986.suite', + 'tests.test_rfc3058.suite', + 'tests.test_rfc3114.suite', + 'tests.test_rfc3125.suite', + 'tests.test_rfc3161.suite', + 'tests.test_rfc3274.suite', + 'tests.test_rfc3279.suite', + 'tests.test_rfc3280.suite', + 'tests.test_rfc3281.suite', + 'tests.test_rfc3370.suite', + 'tests.test_rfc3447.suite', + 'tests.test_rfc3537.suite', + 'tests.test_rfc3560.suite', + 'tests.test_rfc3565.suite', + 'tests.test_rfc3657.suite', + 'tests.test_rfc3709.suite', + 'tests.test_rfc3739.suite', + 'tests.test_rfc3770.suite', + 'tests.test_rfc3779.suite', + 'tests.test_rfc3820.suite', + 'tests.test_rfc3852.suite', + 'tests.test_rfc4010.suite', + 'tests.test_rfc4043.suite', + 'tests.test_rfc4055.suite', + 'tests.test_rfc4073.suite', + 'tests.test_rfc4108.suite', 'tests.test_rfc4210.suite', + 'tests.test_rfc4211.suite', + 'tests.test_rfc4334.suite', + 'tests.test_rfc4357.suite', + 'tests.test_rfc4387.suite', + 'tests.test_rfc4476.suite', + 'tests.test_rfc4490.suite', + 'tests.test_rfc4491.suite', + 'tests.test_rfc4683.suite', + 'tests.test_rfc4985.suite', + 'tests.test_rfc5035.suite', + 'tests.test_rfc5083.suite', + 'tests.test_rfc5084.suite', + 'tests.test_rfc5126.suite', 'tests.test_rfc5208.suite', + 'tests.test_rfc5275.suite', 'tests.test_rfc5280.suite', - 'tests.test_rfc5652.suite',] + 'tests.test_rfc5480.suite', + 'tests.test_rfc5636.suite', + 'tests.test_rfc5639.suite', + 'tests.test_rfc5649.suite', + 'tests.test_rfc5652.suite', + 'tests.test_rfc5697.suite', + 'tests.test_rfc5751.suite', + 'tests.test_rfc5752.suite', + 'tests.test_rfc5753.suite', + 'tests.test_rfc5755.suite', + 'tests.test_rfc5913.suite', + 'tests.test_rfc5914.suite', + 'tests.test_rfc5915.suite', + 'tests.test_rfc5916.suite', + 'tests.test_rfc5917.suite', + 'tests.test_rfc5924.suite', + 'tests.test_rfc5934.suite', + 'tests.test_rfc5940.suite', + 'tests.test_rfc5958.suite', + 'tests.test_rfc5990.suite', + 'tests.test_rfc6010.suite', + 'tests.test_rfc6019.suite', + 'tests.test_rfc6031.suite', + 'tests.test_rfc6032.suite', + 'tests.test_rfc6120.suite', + 'tests.test_rfc6187.suite', + 'tests.test_rfc6210.suite', + 'tests.test_rfc6211.suite', + 'tests.test_rfc6482.suite', + 'tests.test_rfc6486.suite', + 'tests.test_rfc6487.suite', + 'tests.test_rfc6664.suite', + 'tests.test_rfc6955.suite', + 'tests.test_rfc6960.suite', + 'tests.test_rfc7030.suite', + 'tests.test_rfc7191.suite', + 'tests.test_rfc7229.suite', + 'tests.test_rfc7292.suite', + 'tests.test_rfc7296.suite', + 'tests.test_rfc7508.suite', + 'tests.test_rfc7585.suite', + 'tests.test_rfc7633.suite', + 'tests.test_rfc7773.suite', + 'tests.test_rfc7894.suite', + 'tests.test_rfc7906.suite', + 'tests.test_rfc7914.suite', + 'tests.test_rfc8017.suite', + 'tests.test_rfc8018.suite', + 'tests.test_rfc8103.suite', + 'tests.test_rfc8209.suite', + 'tests.test_rfc8226.suite', + 'tests.test_rfc8358.suite', + 'tests.test_rfc8360.suite', + 'tests.test_rfc8398.suite', + 'tests.test_rfc8410.suite', + 'tests.test_rfc8418.suite', + 'tests.test_rfc8419.suite', + 'tests.test_rfc8479.suite', + 'tests.test_rfc8494.suite', + 'tests.test_rfc8520.suite', + 'tests.test_rfc8619.suite', + 'tests.test_rfc8649.suite', + 'tests.test_rfc8692.suite', + 'tests.test_rfc8696.suite', + 'tests.test_rfc8702.suite', + 'tests.test_rfc8708.suite', + 'tests.test_rfc8769.suite'] ) if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite) + import sys + + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_missing.py b/tests/test_missing.py new file mode 100644 index 0000000..0b3f58a --- /dev/null +++ b/tests/test_missing.py @@ -0,0 +1,18 @@ +# +# This file is part of pyasn1-modules software. +# +import sys +import unittest + +# modules without tests +from pyasn1_modules import ( + rfc1155, rfc1157, rfc1901, rfc3412, rfc3414 +) + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + import sys + + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_pem.py b/tests/test_pem.py new file mode 100644 index 0000000..dbcca5a --- /dev/null +++ b/tests/test_pem.py @@ -0,0 +1,103 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.compat.octets import ints2octs +from pyasn1_modules import pem + + +class PemTestCase(unittest.TestCase): + pem_text = """\ +MIIDATCCAekCAQAwgZkxCzAJBgNVBAYTAlJVMRYwFAYDVQQIEw1Nb3Njb3cgUmVn +aW9uMQ8wDQYDVQQHEwZNb3Njb3cxGjAYBgNVBAoTEVNOTVAgTGFib3JhdG9yaWVz +MQwwCgYDVQQLFANSJkQxFTATBgNVBAMTDHNubXBsYWJzLmNvbTEgMB4GCSqGSIb3 +DQEJARYRaW5mb0Bzbm1wbGFicy5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQC9n2NfGS98JDBmAXQn+vNUyPB3QPYC1cwpX8UMYh9MdAmBZJCnvXrQ +Pp14gNAv6AQKxefmGES1b+Yd+1we9HB8AKm1/8xvRDUjAvy4iO0sqFCPvIfSujUy +pBcfnR7QE2itvyrMxCDSEVnMhKdCNb23L2TptUmpvLcb8wfAMLFsSu2yaOtJysep +oH/mvGqlRv2ti2+E2YA0M7Pf83wyV1XmuEsc9tQ225rprDk2uyshUglkDD2235rf +0QyONq3Aw3BMrO9ss1qj7vdDhVHVsxHnTVbEgrxEWkq2GkVKh9QReMZ2AKxe40j4 +og+OjKXguOCggCZHJyXKxccwqCaeCztbAgMBAAGgIjAgBgkqhkiG9w0BCQIxExMR +U05NUCBMYWJvcmF0b3JpZXMwDQYJKoZIhvcNAQEFBQADggEBAAihbwmN9M2bsNNm +9KfxqiGMqqcGCtzIlpDz/2NVwY93cEZsbz3Qscc0QpknRmyTSoDwIG+1nUH0vzkT +Nv8sBmp9I1GdhGg52DIaWwL4t9O5WUHgfHSJpPxZ/zMP2qIsdPJ+8o19BbXRlufc +73c03H1piGeb9VcePIaulSHI622xukI6f4Sis49vkDaoi+jadbEEb6TYkJQ3AMRD +WdApGGm0BePdLqboW1Yv70WRRFFD8sxeT7Yw4qrJojdnq0xMHPGfKpf6dJsqWkHk +b5DRbjil1Zt9pJuF680S9wtBzSi0hsMHXR9TzS7HpMjykL2nmCVY6A78MZapsCzn +GGbx7DI= +""" + + def testReadBase64fromText(self): + + binary = pem.readBase64fromText(self.pem_text) + + self.assertTrue(binary) + + expected = [ + 48, 130, 3, 1, 48, 130, 1, 233, 2, 1, 0, 48, 129, 153, 49, 11, 48, + 9, 6, 3, 85, 4, 6, 19, 2, 82, 85, 49, 22, 48, 20, 6, 3, 85, 4, 8, + 19, 13, 77, 111, 115, 99, 111, 119, 32, 82, 101, 103, 105, 111, + 110, 49, 15, 48, 13, 6, 3, 85, 4, 7, 19, 6, 77, 111, 115, 99, 111, + 119, 49, 26, 48, 24, 6, 3, 85, 4, 10, 19, 17, 83, 78, 77, 80, 32, + 76, 97, 98, 111, 114, 97, 116, 111, 114, 105, 101, 115, 49, 12, + 48, 10, 6, 3, 85, 4, 11, 20, 3, 82, 38, 68, 49, 21, 48, 19, 6, 3, + 85, 4, 3, 19, 12, 115, 110, 109, 112, 108, 97, 98, 115, 46, 99, + 111, 109, 49, 32, 48, 30, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 1, + 22, 17, 105, 110, 102, 111, 64, 115, 110, 109, 112, 108, 97, 98, + 115, 46, 99, 111, 109, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, + 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, + 130, 1, 1, 0, 189, 159, 99, 95, 25, 47, 124, 36, 48, 102, 1, 116, + 39, 250, 243, 84, 200, 240, 119, 64, 246, 2, 213, 204, 41, 95, 197, + 12, 98, 31, 76, 116, 9, 129, 100, 144, 167, 189, 122, 208, 62, 157, + 120, 128, 208, 47, 232, 4, 10, 197, 231, 230, 24, 68, 181, 111, + 230, 29, 251, 92, 30, 244, 112, 124, 0, 169, 181, 255, 204, 111, + 68, 53, 35, 2, 252, 184, 136, 237, 44, 168, 80, 143, 188, 135, 210, + 186, 53, 50, 164, 23, 31, 157, 30, 208, 19, 104, 173, 191, 42, 204, + 196, 32, 210, 17, 89, 204, 132, 167, 66, 53, 189, 183, 47, 100, + 233, 181, 73, 169, 188, 183, 27, 243, 7, 192, 48, 177, 108, 74, + 237, 178, 104, 235, 73, 202, 199, 169, 160, 127, 230, 188, 106, + 165, 70, 253, 173, 139, 111, 132, 217, 128, 52, 51, 179, 223, 243, + 124, 50, 87, 85, 230, 184, 75, 28, 246, 212, 54, 219, 154, 233, + 172, 57, 54, 187, 43, 33, 82, 9, 100, 12, 61, 182, 223, 154, 223, + 209, 12, 142, 54, 173, 192, 195, 112, 76, 172, 239, 108, 179, 90, + 163, 238, 247, 67, 133, 81, 213, 179, 17, 231, 77, 86, 196, 130, + 188, 68, 90, 74, 182, 26, 69, 74, 135, 212, 17, 120, 198, 118, 0, + 172, 94, 227, 72, 248, 162, 15, 142, 140, 165, 224, 184, 224, 160, + 128, 38, 71, 39, 37, 202, 197, 199, 48, 168, 38, 158, 11, 59, 91, 2, + 3, 1, 0, 1, 160, 34, 48, 32, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, + 2, 49, 19, 19, 17, 83, 78, 77, 80, 32, 76, 97, 98, 111, 114, 97, + 116, 111, 114, 105, 101, 115, 48, 13, 6, 9, 42, 134, 72, 134, 247, + 13, 1, 1, 5, 5, 0, 3, 130, 1, 1, 0, 8, 161, 111, 9, 141, 244, 205, + 155, 176, 211, 102, 244, 167, 241, 170, 33, 140, 170, 167, 6, 10, + 220, 200, 150, 144, 243, 255, 99, 85, 193, 143, 119, 112, 70, 108, + 111, 61, 208, 177, 199, 52, 66, 153, 39, 70, 108, 147, 74, 128, 240, + 32, 111, 181, 157, 65, 244, 191, 57, 19, 54, 255, 44, 6, 106, 125, + 35, 81, 157, 132, 104, 57, 216, 50, 26, 91, 2, 248, 183, 211, 185, + 89, 65, 224, 124, 116, 137, 164, 252, 89, 255, 51, 15, 218, 162, + 44, 116, 242, 126, 242, 141, 125, 5, 181, 209, 150, 231, 220, 239, + 119, 52, 220, 125, 105, 136, 103, 155, 245, 87, 30, 60, 134, 174, + 149, 33, 200, 235, 109, 177, 186, 66, 58, 127, 132, 162, 179, 143, + 111, 144, 54, 168, 139, 232, 218, 117, 177, 4, 111, 164, 216, 144, + 148, 55, 0, 196, 67, 89, 208, 41, 24, 105, 180, 5, 227, 221, 46, + 166, 232, 91, 86, 47, 239, 69, 145, 68, 81, 67, 242, 204, 94, 79, + 182, 48, 226, 170, 201, 162, 55, 103, 171, 76, 76, 28, 241, 159, + 42, 151, 250, 116, 155, 42, 90, 65, 228, 111, 144, 209, 110, 56, + 165, 213, 155, 125, 164, 155, 133, 235, 205, 18, 247, 11, 65, 205, + 40, 180, 134, 195, 7, 93, 31, 83, 205, 46, 199, 164, 200, 242, 144, + 189, 167, 152, 37, 88, 232, 14, 252, 49, 150, 169, 176, 44, 231, + 24, 102, 241, 236, 50 + ] + + self.assertEqual(ints2octs(expected), binary) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc2314.py b/tests/test_rfc2314.py index 9ff3176..69927a6 100644 --- a/tests/test_rfc2314.py +++ b/tests/test_rfc2314.py @@ -1,23 +1,18 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # import sys +import unittest -from pyasn1.codec.der import decoder as der_decoder -from pyasn1.codec.der import encoder as der_encoder +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder from pyasn1_modules import pem from pyasn1_modules import rfc2314 -try: - import unittest2 as unittest - -except ImportError: - import unittest - class CertificationRequestTestCase(unittest.TestCase): pem_text = """\ @@ -47,14 +42,15 @@ def testDerCodec(self): substrate = pem.readBase64fromText(self.pem_text) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite) + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc2315.py b/tests/test_rfc2315.py index 3a0c307..40030c9 100644 --- a/tests/test_rfc2315.py +++ b/tests/test_rfc2315.py @@ -1,23 +1,18 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # import sys +import unittest -from pyasn1.codec.der import decoder as der_decoder -from pyasn1.codec.der import encoder as der_encoder +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder from pyasn1_modules import pem from pyasn1_modules import rfc2315 -try: - import unittest2 as unittest - -except ImportError: - import unittest - class Pkcs7TestCase(unittest.TestCase): pem_text_unordered = """\ @@ -146,23 +141,25 @@ def testDerCodec(self): substrate = pem.readBase64fromText(self.pem_text_unordered) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) def testDerCodecDecodeOpenTypes(self): substrate = pem.readBase64fromText(self.pem_text_reordered) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual( + substrate, der_encoder(asn1Object, omitEmptyOptionals=False)) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite) + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc2437.py b/tests/test_rfc2437.py index 748a9df..b411756 100644 --- a/tests/test_rfc2437.py +++ b/tests/test_rfc2437.py @@ -1,23 +1,18 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # import sys +import unittest -from pyasn1.codec.der import decoder as der_decoder -from pyasn1.codec.der import encoder as der_encoder +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder from pyasn1_modules import pem from pyasn1_modules import rfc2437 -try: - import unittest2 as unittest - -except ImportError: - import unittest - class RSAPrivateKeyTestCase(unittest.TestCase): pem_text = """\ @@ -37,14 +32,15 @@ def testDerCodec(self): substrate = pem.readBase64fromText(self.pem_text) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite) + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc2459.py b/tests/test_rfc2459.py index 20a0d28..4132daa 100644 --- a/tests/test_rfc2459.py +++ b/tests/test_rfc2459.py @@ -1,23 +1,18 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # import sys +import unittest -from pyasn1.codec.der import decoder as der_decoder -from pyasn1.codec.der import encoder as der_encoder +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder from pyasn1_modules import pem from pyasn1_modules import rfc2459 -try: - import unittest2 as unittest - -except ImportError: - import unittest - class CertificateTestCase(unittest.TestCase): pem_text = """\ @@ -46,21 +41,22 @@ def testDerCodec(self): substrate = pem.readBase64fromText(self.pem_text) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(der_encoder(asn1Object), substrate) def testDerCodecDecodeOpenTypes(self): substrate = pem.readBase64fromText(self.pem_text) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(der_encoder(asn1Object), substrate) class CertificateListTestCase(unittest.TestCase): @@ -82,21 +78,22 @@ def testDerCodec(self): substrate = pem.readBase64fromText(self.pem_text) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(der_encoder(asn1Object), substrate) def testDerCodecDecodeOpenTypes(self): substrate = pem.readBase64fromText(self.pem_text) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(der_encoder(asn1Object), substrate) class DSAPrivateKeyTestCase(unittest.TestCase): @@ -120,25 +117,26 @@ def testDerCodec(self): substrate = pem.readBase64fromText(self.pem_text) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) def testDerCodecDecodeOpenTypes(self): substrate = pem.readBase64fromText(self.pem_text) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) - - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite) + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc2511.py b/tests/test_rfc2511.py index cd5e266..057b7fe 100644 --- a/tests/test_rfc2511.py +++ b/tests/test_rfc2511.py @@ -1,23 +1,18 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # import sys +import unittest -from pyasn1.codec.der import decoder as der_decoder -from pyasn1.codec.der import encoder as der_encoder +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder from pyasn1_modules import pem from pyasn1_modules import rfc2511 -try: - import unittest2 as unittest - -except ImportError: - import unittest - class CertificateReqTestCase(unittest.TestCase): pem_text = """\ @@ -39,14 +34,15 @@ def testDerCodec(self): substrate = pem.readBase64fromText(self.pem_text) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite) + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc2560.py b/tests/test_rfc2560.py index f96d36b..eef5451 100644 --- a/tests/test_rfc2560.py +++ b/tests/test_rfc2560.py @@ -1,23 +1,18 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # import sys +import unittest -from pyasn1.codec.der import decoder as der_decoder -from pyasn1.codec.der import encoder as der_encoder +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder from pyasn1_modules import pem from pyasn1_modules import rfc2560 -try: - import unittest2 as unittest - -except ImportError: - import unittest - class OCSPRequestTestCase(unittest.TestCase): pem_text = """\ @@ -32,11 +27,11 @@ def testDerCodec(self): substrate = pem.readBase64fromText(self.pem_text) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(der_encoder(asn1Object), substrate) class OCSPResponseTestCase(unittest.TestCase): @@ -71,14 +66,15 @@ def setUp(self): def testDerCodec(self): substrate = pem.readBase64fromText(self.pem_text) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite) + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc2631.py b/tests/test_rfc2631.py new file mode 100644 index 0000000..ca9e547 --- /dev/null +++ b/tests/test_rfc2631.py @@ -0,0 +1,41 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc2631 + + +class OtherInfoTestCase(unittest.TestCase): + pem_text = "MB0wEwYLKoZIhvcNAQkQAwYEBAAAAAGiBgQEAAAAwA==" + + def setUp(self): + self.asn1Spec = rfc2631.OtherInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + hex1 = univ.OctetString(hexValue='00000001') + self.assertEqual(hex1, asn1Object['keyInfo']['counter']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc2634.py b/tests/test_rfc2634.py new file mode 100644 index 0000000..225b987 --- /dev/null +++ b/tests/test_rfc2634.py @@ -0,0 +1,191 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc2634 + + +class SignedMessageTestCase(unittest.TestCase): + signed_message_pem_text = """\ +MIIFLgYJKoZIhvcNAQcCoIIFHzCCBRsCAQExDTALBglghkgBZQMEAgIwUQYJKoZI +hvcNAQcBoEQEQkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbg0KDQpXYXRzb24sIGNv +bWUgaGVyZSAtIEkgd2FudCB0byBzZWUgeW91LqCCAnwwggJ4MIIB/qADAgECAgkA +pbNUKBuwbjswCgYIKoZIzj0EAwMwPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZB +MRAwDgYDVQQHDAdIZXJuZG9uMREwDwYDVQQKDAhCb2d1cyBDQTAeFw0xOTA1Mjkx +NDQ1NDFaFw0yMDA1MjgxNDQ1NDFaMHAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJW +QTEQMA4GA1UEBxMHSGVybmRvbjEQMA4GA1UEChMHRXhhbXBsZTEOMAwGA1UEAxMF +QWxpY2UxIDAeBgkqhkiG9w0BCQEWEWFsaWNlQGV4YW1wbGUuY29tMHYwEAYHKoZI +zj0CAQYFK4EEACIDYgAE+M2fBy/sRA6V1pKFqecRTE8+LuAHtZxes1wmJZrBBg+b +z7uYZfYQxI3dVB0YCSD6Mt3yXFlnmfBRwoqyArbjIBYrDbHBv2k8Csg2DhQ7qs/w +to8hMKoFgkcscqIbiV7Zo4GUMIGRMAsGA1UdDwQEAwIHgDBCBglghkgBhvhCAQ0E +NRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUgdHJ1c3RlZCBmb3IgYW55IHB1 +cnBvc2UuMB0GA1UdDgQWBBTEuloOPnrjPIGw9AKqaLsW4JYONTAfBgNVHSMEGDAW +gBTyNds0BNqlVfK9aQOZsGLs4hUIwTAKBggqhkjOPQQDAwNoADBlAjBjuR/RNbgL +3kRhmn+PJTeKaL9sh/oQgHOYTgLmSnv3+NDCkhfKuMNoo/tHrkmihYgCMQC94Mae +rDIrQpi0IDh+v0QSAv9rMife8tClafXWtDwwL8MS7oAh0ymT446Uizxx3PUxggIy +MIICLgIBATBMMD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwH +SGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0ECCQCls1QoG7BuOzALBglghkgBZQME +AgKgggFXMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8X +DTE5MDUyOTE4MjMxOVowJQYLKoZIhvcNAQkQAgcxFgQUAbWZQYhLO5wtUgsOCGtT +4V3aNhUwLwYLKoZIhvcNAQkQAgQxIDAeDBFXYXRzb24sIGNvbWUgaGVyZQYJKoZI +hvcNAQcBMDUGCyqGSIb3DQEJEAICMSYxJAIBAQYKKwYBBAGBrGABARMTQm9hZ3Vz +IFByaXZhY3kgTWFyazA/BgkqhkiG9w0BCQQxMgQwtuQipP2CZx7U96rGbUT06LC5 +jVFYccZW5/CaNvpcrOPiChDm2vI3m4k300z5mSZsME0GCyqGSIb3DQEJEAIBMT4w +PAQgx08hD2QnVwj1DoeRELNtdZ0PffW4BQIvcwwVc/goU6OAAQEwFTATgRFhbGlj +ZUBleGFtcGxlLmNvbTAKBggqhkjOPQQDAwRnMGUCMAFFVP2gYFLTbaxvV5J2ICNM +Nk/K4pXbj5Zvj3dcCeC4+OUYyG3ZW5lOtKqaabEAXAIxALDg1WOouhkDfwuQdgBi +mNTr0mjYeUWRe/15IsWNx+kuFcLDr71DFHvMFY5M3sdfMA== +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.signed_message_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + sd, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.SignedData()) + + self.assertFalse(rest) + self.assertTrue(sd.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(sd)) + + for sa in sd['signerInfos'][0]['signedAttrs']: + sat = sa['attrType'] + sav0 = sa['attrValues'][0] + + if sat in rfc5652.cmsAttributesMap.keys(): + sav, rest = der_decoder( + sav0, asn1Spec=rfc5652.cmsAttributesMap[sat]) + self.assertFalse(rest) + self.assertTrue(sav.prettyPrint()) + self.assertEqual(sav0, der_encoder(sav)) + + +class SignedReceiptTestCase(unittest.TestCase): + signed_receipt_pem_text = """\ +MIIE3gYJKoZIhvcNAQcCoIIEzzCCBMsCAQMxDTALBglghkgBZQMEAgEwga4GCyq +GSIb3DQEJEAEBoIGeBIGbMIGYAgEBBgkqhkiG9w0BBwEEIMdPIQ9kJ1cI9Q6HkR +CzbXWdD331uAUCL3MMFXP4KFOjBGYwZAIwOLV5WCbYjy5HLHE69IqXQQHVDJQzm +o18WwkFrEYH3EMsvpXEIGqsFTFN6NV4VBe9AjA5fGOCP5IhI32YqmGfs+zDlqZy +b2xSX6Gr/IfCIm0angfOI39g7lAZDyivjh5H/oSgggJ3MIICczCCAfqgAwIBAgI +JAKWzVCgbsG48MAoGCCqGSM49BAMDMD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDA +JWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0EwHhcNMTkwN +TI5MTkyMDEzWhcNMjAwNTI4MTkyMDEzWjBsMQswCQYDVQQGEwJVUzELMAkGA1UE +CBMCVkExEDAOBgNVBAcTB0hlcm5kb24xEDAOBgNVBAoTB0V4YW1wbGUxDDAKBgN +VBAMTA0JvYjEeMBwGCSqGSIb3DQEJARYPYm9iQGV4YW1wbGUuY29tMHYwEAYHKo +ZIzj0CAQYFK4EEACIDYgAEMaRiVS8WvN8Ycmpfq75jBbOMUukNfXAg6AL0JJBXt +IFAuIJcZVlkLn/xbywkcMLHK/O+w9RWUQa2Cjw+h8b/1Cl+gIpqLtE558bD5PfM +2aYpJ/YE6yZ9nBfTQs7z1TH5o4GUMIGRMAsGA1UdDwQEAwIHgDBCBglghkgBhvh +CAQ0ENRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUgdHJ1c3RlZCBmb3IgYW +55IHB1cnBvc2UuMB0GA1UdDgQWBBTKa2Zy3iybV3+YjuLDKtNmjsIapTAfBgNVH +SMEGDAWgBTyNds0BNqlVfK9aQOZsGLs4hUIwTAKBggqhkjOPQQDAwNnADBkAjAV +boS6OfEYQomLDi2RUkd71hzwwiQZztbxNbosahIzjR8ZQaHhjdjJlrP/T6aXBws +CMDfRweYz3Ce4E4wPfoqQnvqpM7ZlfhstjQQGOsWAtIIfqW/l+TgCO8ux3XLV6f +j36zGCAYkwggGFAgEBMEwwPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMRAwD +gYDVQQHDAdIZXJuZG9uMREwDwYDVQQKDAhCb2d1cyBDQQIJAKWzVCgbsG48MAsG +CWCGSAFlAwQCAaCBrjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQEwHAYJKoZ +IhvcNAQkFMQ8XDTE5MDUyOTE5MzU1NVowLwYJKoZIhvcNAQkEMSIEIGb9Hm2kCn +M0CYNpZU4Uj7dN0AzOieIn9sDqZMcIcZrEMEEGCyqGSIb3DQEJEAIFMTIEMBZze +HVja7fQ62ywyh8rtKzBP1WJooMdZ+8c6pRqfIESYIU5bQnH99OPA51QCwdOdjAK +BggqhkjOPQQDAgRoMGYCMQDZiT22xgab6RFMAPvN4fhWwzx017EzttD4VaYrpbo +lropBdPJ6jIXiZQgCwxbGTCwCMQClaQ9K+L5LTeuW50ZKSIbmBZQ5dxjtnK3OlS +7hYRi6U0JKZmWbbuS8vFIgX7eIkd8= +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.signed_receipt_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(asn1Object['contentType'], rfc5652.id_signedData) + + sd, rest = der_decoder(asn1Object['content'], asn1Spec=rfc5652.SignedData()) + + self.assertFalse(rest) + + self.assertTrue(sd.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(sd)) + self.assertEqual(sd['encapContentInfo']['eContentType'], + rfc2634.id_ct_receipt) + + receipt, rest = der_decoder(sd['encapContentInfo']['eContent'], + asn1Spec=rfc2634.Receipt()) + + self.assertFalse(rest) + self.assertTrue(receipt.prettyPrint()) + self.assertEqual(sd['encapContentInfo']['eContent'], der_encoder(receipt)) + self.assertEqual(receipt['version'], rfc2634.ESSVersion().subtype(value='v1')) + + for sa in sd['signerInfos'][0]['signedAttrs']: + sat = sa['attrType'] + sav0 = sa['attrValues'][0] + + if sat in rfc5652.cmsAttributesMap.keys(): + sav, rest = der_decoder(sav0, asn1Spec=rfc5652.cmsAttributesMap[sat]) + + self.assertFalse(rest) + self.assertTrue(sav.prettyPrint()) + self.assertEqual(sav0, der_encoder(sav)) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.signed_receipt_pem_text) + asn1Object, rest = der_decoder(substrate, + asn1Spec=self.asn1Spec, + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertIn(asn1Object['contentType'], rfc5652.cmsContentTypesMap.keys()) + self.assertEqual(asn1Object['contentType'], rfc5652.id_signedData) + + sd = asn1Object['content'] + + self.assertEqual(sd['version'], rfc5652.CMSVersion().subtype(value='v3')) + self.assertIn(sd['encapContentInfo']['eContentType'], rfc5652.cmsContentTypesMap) + self.assertEqual(sd['encapContentInfo']['eContentType'], rfc2634.id_ct_receipt) + + for sa in sd['signerInfos'][0]['signedAttrs']: + + self.assertIn(sa['attrType'], rfc5652.cmsAttributesMap) + + if sa['attrType'] == rfc2634.id_aa_msgSigDigest: + sa['attrValues'][0].prettyPrint()[:10] == '0x167378' + + # Since receipt is inside an OCTET STRING, decodeOpenTypes=True cannot + # automatically decode it + receipt, rest = der_decoder(sd['encapContentInfo']['eContent'], + asn1Spec=rfc5652.cmsContentTypesMap[sd['encapContentInfo']['eContentType']]) + + self.assertEqual(receipt['version'], rfc2634.ESSVersion().subtype(value='v1')) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc2876.py b/tests/test_rfc2876.py new file mode 100644 index 0000000..177e038 --- /dev/null +++ b/tests/test_rfc2876.py @@ -0,0 +1,185 @@ +# +# 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.type import univ + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc2876 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5751 + +try: + import unittest2 as unittest +except ImportError: + import unittest + + +class EnvelopedDataTestCase(unittest.TestCase): + env_data_pem_text = """\ +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 +z10epK+S +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.env_data_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual(rfc5652.id_envelopedData, asn1Object['contentType']) + ed, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.EnvelopedData()) + self.assertFalse(rest) + self.assertTrue(ed.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(ed)) + + kari_kea = ed['recipientInfos'][0]['kari']['keyEncryptionAlgorithm'] + self.assertEqual(rfc2876.id_kEAKeyEncryptionAlgorithm, kari_kea['algorithm']) + kwa, rest = der_decoder( + kari_kea['parameters'], asn1Spec=rfc5280.AlgorithmIdentifier()) + self.assertFalse(rest) + self.assertTrue(kwa.prettyPrint()) + self.assertEqual(kari_kea['parameters'], der_encoder(kwa)) + self.assertEqual(rfc2876.id_fortezzaWrap80, kwa['algorithm']) + + cea = ed['encryptedContentInfo']['contentEncryptionAlgorithm'] + self.assertEqual(rfc2876.id_fortezzaConfidentialityAlgorithm, cea['algorithm']) + param, rest = der_decoder(cea['parameters'], rfc2876.Skipjack_Parm()) + self.assertFalse(rest) + self.assertTrue(param.prettyPrint()) + self.assertEqual(cea['parameters'], der_encoder(param)) + + iv = univ.OctetString(hexValue='424f4755535f4956') + self.assertEqual(iv, param['initialization-vector']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.env_data_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertIn(asn1Object['contentType'], rfc5652.cmsContentTypesMap.keys()) + kari_kea = asn1Object['content']['recipientInfos'][0]['kari']['keyEncryptionAlgorithm'] + self.assertEqual(rfc2876.id_kEAKeyEncryptionAlgorithm, kari_kea['algorithm']) + self.assertEqual(rfc2876.id_fortezzaWrap80, kari_kea['parameters']['algorithm']) + + cea = asn1Object['content']['encryptedContentInfo']['contentEncryptionAlgorithm'] + self.assertEqual(rfc2876.id_fortezzaConfidentialityAlgorithm, cea['algorithm']) + + iv = univ.OctetString(hexValue='424f4755535f4956') + self.assertEqual(iv, cea['parameters']['initialization-vector']) + +class SMIMECapabilitiesTestCase(unittest.TestCase): + smime_capabilities_pem_text = "\ +MCcwGAYJYIZIAWUCAQEYMAsGCWCGSAFlAgEBFzALBglghkgBZQIBAQQ=" + + def setUp(self): + self.asn1Spec = rfc5751.SMIMECapabilities() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.smime_capabilities_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + found_wrap_alg = False + for cap in asn1Object: + if cap['capabilityID'] in rfc5751.smimeCapabilityMap.keys(): + if cap['parameters'].hasValue(): + param, rest = der_decoder( + cap['parameters'], + asn1Spec=rfc5751.smimeCapabilityMap[cap['capabilityID']]) + self.assertFalse(rest) + self.assertTrue(param.prettyPrint()) + self.assertEqual(cap['parameters'], der_encoder(param)) + + if cap['capabilityID'] == rfc2876.id_kEAKeyEncryptionAlgorithm: + self.assertEqual(rfc2876.id_fortezzaWrap80, param['algorithm']) + found_wrap_alg = True + + self.assertTrue(found_wrap_alg) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.smime_capabilities_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + found_wrap_alg = False + for cap in asn1Object: + if cap['capabilityID'] == rfc2876.id_kEAKeyEncryptionAlgorithm: + self.assertEqual(rfc2876.id_fortezzaWrap80, cap['parameters']['algorithm']) + found_wrap_alg = True + + self.assertTrue(found_wrap_alg) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc2985.py b/tests/test_rfc2985.py new file mode 100644 index 0000000..376475e --- /dev/null +++ b/tests/test_rfc2985.py @@ -0,0 +1,319 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc2985 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc7292 + + +class PKCS9AttrsTestCase(unittest.TestCase): + pem_text = """\ +MYIQjzAOBgNVBEExBwwFQWxpY2UwDwYIKwYBBQUHCQMxAxMBTTAQBgNVBAUxCRMH +QjQ4LTAwNzAQBggrBgEFBQcJBDEEEwJVUzAQBggrBgEFBQcJBTEEEwJVUzARBgoq +hkiG9w0BCRkEMQMCATAwFAYJKoZIhvcNAQkCMQcWBUFsaWNlMBgGCiqGSIb3DQEJ +GQMxCgQIUTeqnHYky4AwHAYJKoZIhvcNAQkPMQ8wDTALBglghkgBZQMEAS0wHQYI +KwYBBQUHCQExERgPMjAxOTA4MDMxMjAwMDBaMB0GCCsGAQUFBwkCMREMD0hlcm5k +b24sIFZBLCBVUzApBgkqhkiG9w0BCRQxHB4aAEYAcgBpAGUAbgBkAGwAeQAgAE4A +YQBtAGUwLwYJKoZIhvcNAQkIMSITIDEyMyBVbmtub3duIFdheSwgTm93aGVyZSwg +VkEsIFVTMIGZBgoqhkiG9w0BCRkCMYGKMIGHMAsGCWCGSAFlAwQBLQR4VsJb7t4l +IqjJCT54rqkbCJsBPE17YQJeEYvyA4M1aDIUU5GnCgEhctgMiDPWGMvaSziixdIg +aU/0zvWvYCm8UwPvBBwMtm9X5NDvk9p4nXbGAT8E/OsV1SYWVvwRJwYak0yWWexM +HSixw1Ljh2nb0fIbqwLOeMmIMIIEsQYKKoZIhvcNAQkZBTGCBKEwggSdBgkqhkiG +9w0BBwKgggSOMIIEigIBATENMAsGCWCGSAFlAwQCAjBRBgkqhkiG9w0BBwGgRARC +Q29udGVudC1UeXBlOiB0ZXh0L3BsYWluDQoNCldhdHNvbiwgY29tZSBoZXJlIC0g +SSB3YW50IHRvIHNlZSB5b3UuoIICfDCCAngwggH+oAMCAQICCQCls1QoG7BuOzAK +BggqhkjOPQQDAzA/MQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkExEDAOBgNVBAcM +B0hlcm5kb24xETAPBgNVBAoMCEJvZ3VzIENBMB4XDTE5MDUyOTE0NDU0MVoXDTIw +MDUyODE0NDU0MVowcDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlZBMRAwDgYDVQQH +EwdIZXJuZG9uMRAwDgYDVQQKEwdFeGFtcGxlMQ4wDAYDVQQDEwVBbGljZTEgMB4G +CSqGSIb3DQEJARYRYWxpY2VAZXhhbXBsZS5jb20wdjAQBgcqhkjOPQIBBgUrgQQA +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 +9t33YdzJaFbz+8jb88xtf454Rvur66Cew/4GYX9u1Zef0DF9So1ay3IicpOf5emo +VWIwg4bh7bELi78i/MbdWtNZQcXimykfeTsYH8Q4u+1uxHS5pwEWWwKiUnLQVpZP +2ut255TdgSIhEILwsaLVelRrx/lp14EpY355FOusXiju6g14aWfBnt5udvuTXxDQ +ZHPPNNk+gwzgvvTey98T941hYUctjg0NApJiB66bfrlYB9mkc5ftg5zqhEasYH5C +4ajKKRNMM7zGlwSZvy8PPhnAeE3Q9LTnos0l4ygjQD/kMlvd7XSLW3GUzjyxtkG4 +gQh6LGvnafAbgu7GpcapKEppN86sXEePHiQjj92n103+TxMYWwtaO4iAwkjqdEdt +avEHcXRcpdqC0st6nUwPAPAC4LKJbZgLQnNG+wlWIiCMMD56IdfQ7r/zGIr13MxC +kjNNUdISoWWE5GnQMYHbMBMGCSqGSIb3DQEJFTEGBAQBAAAAMFcGCSqGSIb3DQEJ +FDFKHkgAMwBmADcAMQBhAGYANgA1AC0AMQA2ADgANwAtADQANAA0AGEALQA5AGYA +NAA2AC0AYwA4AGIAZQAxADkANABjADMAZQA4AGUwawYJKwYBBAGCNxEBMV4eXABN +AGkAYwByAG8AcwBvAGYAdAAgAEUAbgBoAGEAbgBjAGUAZAAgAEMAcgB5AHAAdABv +AGcAcgBhAHAAaABpAGMAIABQAHIAbwB2AGkAZABlAHIAIAB2ADEALgAwMIIDaAYJ +KoZIhvcNAQcBoIIDWQSCA1UwggNRMIIDTQYLKoZIhvcNAQwKAQOgggMlMIIDIQYK +KoZIhvcNAQkWAaCCAxEEggMNMIIDCTCCAfGgAwIBAgIQNu32hzqhCKdHATXzboyI +ETANBgkqhkiG9w0BAQUFADAUMRIwEAYDVQQDEwlhbm9ueW1vdXMwIBcNMTYwNzE5 +MjIwMDAxWhgPMjExNjA2MjUyMjAwMDFaMBQxEjAQBgNVBAMTCWFub255bW91czCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALy2sEJMGNdcDg6BI7mdFM5T +lPzo5sKBzvUnagK5SKBJ11xMPN5toPTBzICB/XTWEB3AwpD0O+srSca+bsUAyedS +5V4BNp8qCyEu5RNRR8qPHheJ/guhLT96/gGI4jlrUyUhFntPkLKODxu+7KanMy6K +dD+PVE8shXRUZTYe4PG64/c7z3wapnf4XoCXkJRzCY5f3MKz3Ul039kVnTlJcikd +C7I9I9RflXLwXVl4nxUbeeRt6Z8WVWS4pCq+14v2aVPvP3mtVmAYHedRkvS04Hrx +4xx98D3NSSw6Z5OLkzqOcFw15fYmH2NLdhh34gSWJmaaCBAbuQ+1rx/42p7MvvsC +AwEAAaNVMFMwFQYDVR0lBA4wDAYKKwYBBAGCNwoDBDAvBgNVHREEKDAmoCQGCisG +AQQBgjcUAgOgFgwUYW5vbnltb3VzQHdpbmRvd3MteAAwCQYDVR0TBAIwADANBgkq +hkiG9w0BAQUFAAOCAQEAuH7iqY0/MLozwFb39ILYAJDHE+HToZBQbHQP4YtienrU +Stk60rIp0WH65lam7m/JhgAcItc/tV1L8mEnLrvvKcA+NeIL8sDOtM28azvgcOi0 +P3roeLLLRCuiykUaKmUcZEDm9cDYKIpJf7QetWQ3uuGTk9iRzpH79x2ix35BnyWQ +Rr3INZzmX/+9YRvPBXKYl/89F/w1ORYArpI9XtjfuPWaGQmM4f1WRHE2t3qRyKFF +ri7QiZdpcSx5zvsRHSyjfUMoKs+b6upk+P01lIhg/ewwYngGab+fZhF15pTNN2hx +8PdNGcrGzrkNKCmJKrWCa2xczuMA+z8SCuC1tYTKmDEVMBMGCSqGSIb3DQEJFTEG +BAQBAAAAMDswHzAHBgUrDgMCGgQUpWCP/fZR0TK5BwGuqvTd0+duiKcEFJTubF2k +HktMK+isIjxOTk4yJTOOAgIH0A== +""" + + def setUp(self): + self.asn1Spec = rfc2985.AttributeSet() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(der_encoder(asn1Object), substrate) + + openTypesMap = { + rfc2985.pkcs_9_at_smimeCapabilities: rfc2985.SMIMECapabilities(), + } + openTypesMap.update(rfc5280.certificateAttributesMap) + openTypesMap.update(rfc5652.cmsAttributesMap) + + for attr in asn1Object: + self.assertIn(attr['type'], openTypesMap) + + av, rest = der_decoder( + attr['values'][0], asn1Spec=openTypesMap[attr['type']]) + + self.assertFalse(rest) + self.assertTrue(av.prettyPrint()) + self.assertEqual(attr['values'][0], der_encoder(av)) + + if attr['type'] == rfc2985.pkcs_9_at_userPKCS12: + + self.assertEqual(univ.Integer(3), av['version']) + self.assertEqual(rfc5652.id_data, av['authSafe']['contentType']) + + outdata, rest = der_decoder( + av['authSafe']['content'], asn1Spec=univ.OctetString()) + + self.assertFalse(rest) + + authsafe, rest = der_decoder( + outdata, asn1Spec=rfc7292.AuthenticatedSafe()) + + self.assertFalse(rest) + + for ci in authsafe: + self.assertEqual(rfc5652.id_data, ci['contentType']) + + indata, rest = der_decoder( + ci['content'], asn1Spec=univ.OctetString()) + + self.assertFalse(rest) + + sc, rest = der_decoder( + indata, asn1Spec=rfc7292.SafeContents()) + + self.assertFalse(rest) + + for sb in sc: + if sb['bagId'] in rfc7292.pkcs12BagTypeMap: + bv, rest = der_decoder( + sb['bagValue'], asn1Spec=rfc7292.pkcs12BagTypeMap[sb['bagId']]) + + self.assertFalse(rest) + + for bagattr in sb['bagAttributes']: + if bagattr['attrType'] in openTypesMap: + inav, rest = der_decoder( + bagattr['attrValues'][0], asn1Spec=openTypesMap[bagattr['attrType']]) + + self.assertFalse(rest) + + if bagattr['attrType'] == rfc2985.pkcs_9_at_friendlyName: + self.assertEqual( "3f71af65-1687-444a-9f46-c8be194c3e8e", inav) + + if bagattr['attrType'] == rfc2985.pkcs_9_at_localKeyId: + self.assertEqual(univ.OctetString(hexValue='01000000'), inav) + + if attr['type'] == rfc2985.pkcs_9_at_pkcs7PDU: + ci, rest = der_decoder( + attr['values'][0], asn1Spec=rfc5652.ContentInfo()) + + self.assertFalse(rest) + self.assertEqual(rfc5652.id_signedData, ci['contentType']) + + sd, rest = der_decoder( + ci['content'], asn1Spec=rfc5652.SignedData()) + + self.assertFalse(rest) + self.assertEqual(1, sd['version']) + + for si in sd['signerInfos']: + self.assertEqual(1, si['version']) + + for siattr in si['signedAttrs']: + if siattr['attrType'] in openTypesMap: + siav, rest = der_decoder( + siattr['attrValues'][0], asn1Spec=openTypesMap[siattr['attrType']]) + + self.assertFalse(rest) + + if siattr['attrType'] == rfc2985.pkcs_9_at_contentType: + self.assertEqual(rfc5652.id_data, siav) + + if siattr['attrType'] == rfc2985.pkcs_9_at_messageDigest: + self.assertEqual('b6e422a4', siav.prettyPrint()[2:10]) + + if siattr['attrType'] == rfc2985.pkcs_9_at_signingTime: + self.assertEqual('190529182319Z', siav['utcTime']) + + for choices in sd['certificates']: + for rdn in choices[0]['tbsCertificate']['subject']['rdnSequence']: + if rdn[0]['type'] in openTypesMap: + nv, rest = der_decoder( + rdn[0]['value'], asn1Spec=openTypesMap[rdn[0]['type']]) + self.assertFalse(rest) + + if rdn[0]['type'] == rfc2985.pkcs_9_at_emailAddress: + self.assertEqual('alice@example.com', nv) + + def testOpenTypes(self): + openTypesMap = { + rfc2985.pkcs_9_at_smimeCapabilities: rfc2985.SMIMECapabilities(), + } + openTypesMap.update(rfc5280.certificateAttributesMap) + openTypesMap.update(rfc5652.cmsAttributesMap) + + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, + openTypes=openTypesMap, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + for attr in asn1Object: + self.assertTrue(attr['type'], openTypesMap) + + if attr['type'] == rfc2985.pkcs_9_at_userPKCS12: + + self.assertEqual(univ.Integer(3), attr['values'][0]['version']) + self.assertEqual(rfc5652.id_data, attr['values'][0]['authSafe']['contentType']) + + authsafe, rest = der_decoder( + attr['values'][0]['authSafe']['content'], + asn1Spec=rfc7292.AuthenticatedSafe()) + + self.assertFalse(rest) + + for ci in authsafe: + self.assertEqual(rfc5652.id_data, ci['contentType']) + + indata, rest = der_decoder( + ci['content'], asn1Spec=univ.OctetString()) + + self.assertFalse(rest) + + sc, rest = der_decoder( + indata, asn1Spec=rfc7292.SafeContents(), decodeOpenTypes=True) + + self.assertFalse(rest) + + for sb in sc: + if sb['bagId'] in rfc7292.pkcs12BagTypeMap: + for bagattr in sb['bagAttributes']: + if bagattr['attrType'] in openTypesMap: + + if bagattr['attrType'] == rfc2985.pkcs_9_at_friendlyName: + self.assertEqual( + "3f71af65-1687-444a-9f46-c8be194c3e8e", + bagattr['attrValues'][0]) + + if bagattr['attrType'] == rfc2985.pkcs_9_at_localKeyId: + self.assertEqual( + univ.OctetString(hexValue='01000000'), + bagattr['attrValues'][0]) + + if attr['type'] == rfc2985.pkcs_9_at_pkcs7PDU: + self.assertEqual(rfc5652.id_signedData, attr['values'][0]['contentType']) + self.assertEqual(1, attr['values'][0]['content']['version']) + + for si in attr['values'][0]['content']['signerInfos']: + self.assertEqual(1, si['version']) + + for siattr in si['signedAttrs']: + if siattr['attrType'] in openTypesMap: + + if siattr['attrType'] == rfc2985.pkcs_9_at_contentType: + self.assertEqual(rfc5652.id_data, siattr['attrValues'][0]) + + if siattr['attrType'] == rfc2985.pkcs_9_at_messageDigest: + self.assertEqual('b6e422a4', siattr['attrValues'][0].prettyPrint()[2:10]) + + if siattr['attrType'] == rfc2985.pkcs_9_at_signingTime: + self.assertEqual('190529182319Z', siattr['attrValues'][0]['utcTime']) + + for choices in attr['values'][0]['content']['certificates']: + for rdn in choices[0]['tbsCertificate']['subject']['rdnSequence']: + if rdn[0]['type'] in openTypesMap: + if rdn[0]['type'] == rfc2985.pkcs_9_at_emailAddress: + self.assertEqual('alice@example.com', rdn[0]['value']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc2986.py b/tests/test_rfc2986.py new file mode 100644 index 0000000..91e3d05 --- /dev/null +++ b/tests/test_rfc2986.py @@ -0,0 +1,90 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import char +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc2986 +from pyasn1_modules import rfc5280 + + +class CertificationRequestTestCase(unittest.TestCase): + pem_text = """\ +MIICxjCCAa4CAQAwgYAxCzAJBgNVBAYTAlVTMR0wGwYDVQQDDBRmY3UuZmFrZS5h +ZGRyZXNzLm9yZzEXMBUGA1UEBwwOUGxlYXNhbnQgR3JvdmUxHDAaBgNVBAoME0Zh +a2UgQ29tcGFueSBVbml0ZWQxDTALBgNVBAgMBFV0YWgxDDAKBgNVBAsMA0VuZzCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALvnYesymhLKSm9Llix53BUA +h99xMDBUYk0OB1VIdNQyjmFabHinM+lYUzVzrfcm1xtYB5QYKbsYuwZ4r5WI7qho +CRJy6JwXqKpOe72ScCogxlGDr2QtKjtvyWrRwXBHX1/OqVSZ3hdz3njhKpmq6HgK +87vH26RCSmK8FqCgn+qePfpspA7GzBvYwXhXluQtG7r4yBMKNRTQlPst8Vcy+iK+ +pI8hmQVrzGi8Hgbpr2L9EjPUOlAQEb8hxeKc7s5VhjN/RHMLVMX8YczZYt7mcDKr +3PMwOVmXL1DMCtnS50MA2AxcPWcbQBeGyMroP+DLhAt6y1/IT0H5sQruNQw4euMC +AwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQBQXYQPfH5Wy4o0ZFbKQOO1e3dHV8rl +e8m9Z6qLgJO8rtW+OI+4FavJ6zjUvNVzd9JJxgwQ/1xprwrXh36nPcSyNLpGs7JT +6u7TGQ38QQAOmziLXzauMWGBeLuzWGmOKA1cs5HFGLSmbxF3+0IWpz4GlD86pU1+ +WYyWgWHHAMA+kFYwBUR6CvPkmhshnZ8vrQavoOlcidCJ8o6IGA7N/Z0/NrgIDcoz +YaruhoMrmRKHKNpfamhT0gvqEPBec+UB3uLElESIqaeqYc6eMtUQP3lqyghF6I0M +fi6h7i9VVAZpslaKFfkNg12gLbbsCB1q36l5VXjHY/qe0FIUa9ogRrOi +""" + + def setUp(self): + self.asn1Spec = rfc2986.CertificationRequest() + + def testDerCodec(self): + + substrate = pem.readBase64fromText(self.pem_text) + + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + def testOpenTypes(self): + openTypesMap = { + univ.ObjectIdentifier('1.2.840.113549.1.1.1'): univ.Null(""), + univ.ObjectIdentifier('1.2.840.113549.1.1.5'): univ.Null(""), + univ.ObjectIdentifier('1.2.840.113549.1.1.11'): univ.Null(""), + } + + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, + asn1Spec=rfc2986.CertificationRequest(), + openTypes=openTypesMap, + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + for rdn in asn1Object['certificationRequestInfo']['subject']['rdnSequence']: + for atv in rdn: + if atv['type'] == rfc5280.id_at_countryName: + self.assertEqual(char.PrintableString('US'), atv['value']) + + else: + self.assertGreater(len(atv['value']['utf8String']), 2) + + spki_alg = asn1Object['certificationRequestInfo']['subjectPKInfo']['algorithm'] + + self.assertEqual(univ.Null(""), spki_alg['parameters']) + + sig_alg = asn1Object['signatureAlgorithm'] + + self.assertEqual(univ.Null(""), sig_alg['parameters']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc3058.py b/tests/test_rfc3058.py new file mode 100644 index 0000000..0a0645c --- /dev/null +++ b/tests/test_rfc3058.py @@ -0,0 +1,140 @@ +# +# 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 +import unittest + +from pyasn1.type import univ + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc3058 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5751 + + +class EnvelopedDataTestCase(unittest.TestCase): + env_data_pem_text = """\ +MIIFgwYJKoZIhvcNAQcDoIIFdDCCBXACAQIxXaJbAgEEMCMEEDiCUYXKXu8SzLos +n2xeYP4YDzIwMTkwOTEyMTIwMDAwWjAPBgsrBgEEAYE8BwEBBgUABCB0G/YBGH3L +3RhoG0mK33M8IvRYAOsnHB5MfUAOGF6kuDCCBQoGCSqGSIb3DQEHATAZBgsrBgEE +AYE8BwEBAjAKBAhCT0dVU19JVoCCBOBzx7F6GMkP+C0Q4iuDq0rkSZprg8nuXx/4 +S3IMP999BrJdUAbPYxdQhAwTOZIuueyv00TJe/Eam9yyLuZXy0PFlTRi7KED8L8c +yHsRoEobWGMLvE3D4hEhTGttElqQxBvMxZZgm6kLnNG7j8Z72L4lU4aARLYTQvkt +lJnnfCaccDSiWzU8eXcXdnZAzcKR7CoDc0/XBpdDRddvQ7KXoarXYHuSybt649YD +cpy0SN9gEPqcFPrBB3nusAx4VOTlpx5Z3ZJv/TEymN8KDobNfykBZURTwupO9WaV +JZ3Hd/d8C1SCJn6DHuM1jwDp26WfzO8xCfea08MJrnQbNKsDHwmt4dFZIOvcOnwR +8nNSB/Lt1aUj3GzluHVMyQQyT4AdZDmwFdNmQOBUBLmbWYhtd7t3O7Eqx8bGNa7V +7LL0nvua04aj1oA6ph/G/8jxhByBYdN5Bwg7f1Ga3ZCwju2tFoQnWOCPYTVOjmBE +JshBbNC7KhLpp9+C7/13A9cIC3T7Reuc7m+Fopf9Fabu97yFiyJPS8jSF0EnesNG +R1L1Uvo2Wdc66iECoSrxvezaSgGKB2uLTnaFx4ASVMcP7gDipEOIwuUUuVCqgmWk +HAK0Q9mwhBLLrYrsn9OjDHFpvkWgWNRMLl/v3E9A+grFh2BQHkB4C7keB1ZOfj1S +qDi/+ylM9I1FOYMxVXJn2qHMl+QOkfdMoIATm3n3DiBI97/uX4x5KaX074v0dN31 +WeDcsFsh2ze5Dhx8vLJCaXLzWqkmNHX5G/CjjqE6bSR/awgWLRZQuY/9fMvDpvVJ +uId/+OoWDtMVPIsyQ8w8yZzv+SkuZhsrJMHiKd5qxNQv5sOvC765LMUCNNwj7WzP +hajintFXLAEMpIjk5xt3eIy3hdYla3PQoFfqcHOVX4EFMLBoYwBTgik8Fg669yXt +MlbH84MGNs7jObhP/rrDkgbe0qmxUyzgm2uHya1VcItMGYoPPKMFU3ZfwAsZdqsi +1GAtruTzSUmOpMfAoKOIAyZP96HrsrPCaoGrn7ysm5eRrHQ2hdwO7rGQIw0dRAFh +2eyRomoLam7yEiw9M6uHuJ5hIS5yEW+7uUjQT6nvKlbrkIyLL5j9Gbk5Z4fOMqRT +kBs+3H8x7a+lBEKBo/ByJm6fHYi+LX5ZhQFTWkY0M7tfPtrxQdsNRGSHtv7jS7PZ +3thCMqCtkG/pjAsCbDUtMThtP08z2fstE6dfy7qSx6LzKLDyBl5W76mVYdsX7Q72 +yIoCDFmUGdrRcWA+l3OMwNNL+x9MhhdaUWPtxqaGyZMNGOjkbYHbXZ69oqYqCHkA +stIVKTzpk3kq9C9x+ynzWO8kIGYNK2uxSBIzPLQ6Daq4c53rWFFNWVjPC8m98zMc +Yp0hbBhRsdk4qj8osSTcTfpT0+Q+hkYQvZl4IfgX1aHeaCDSScF8SaU+cZ7GYFvL +o1cYrtVbeXrFwmWl0xpco1Ux+XZgryT/fgfJ+3ToppgsQmzECqTWmYsSYaF1kLU4 +Cqi9UH/VqBLOkwxoH05Zao2xOMNzu2QO3wFnvY2wBsIj1eaxfzVb42o9vom7V20j +T1ufXXctf9ls5J1WJxBxdKmXQWdNloeAcl1AtxTbw7vIUU5uWqu9wwqly11MDVPA +b0tcQW20auWmCNkXd52jQJ7PXR6kr5I= +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.env_data_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_envelopedData, asn1Object['contentType']) + + ed, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.EnvelopedData()) + + self.assertFalse(rest) + self.assertTrue(ed.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(ed)) + + kwa = ed['recipientInfos'][0]['kekri']['keyEncryptionAlgorithm'] + self.assertEqual(rfc3058.id_alg_CMSIDEAwrap, kwa['algorithm']) + self.assertEqual(kwa['parameters'], der_encoder(univ.Null(""))) + + cea = ed['encryptedContentInfo']['contentEncryptionAlgorithm'] + self.assertEqual(rfc3058.id_IDEA_CBC, cea['algorithm']) + param, rest = der_decoder( + cea['parameters'], asn1Spec=rfc3058.IDEA_CBCPar()) + + self.assertFalse(rest) + self.assertTrue(param.prettyPrint()) + self.assertEqual(cea['parameters'], der_encoder(param)) + + iv = univ.OctetString(hexValue='424f4755535f4956') + self.assertEqual(iv, param['iv']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.env_data_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + kekri = asn1Object['content']['recipientInfos'][0]['kekri'] + kwa = kekri['keyEncryptionAlgorithm'] + self.assertEqual(rfc3058.id_alg_CMSIDEAwrap, kwa['algorithm']) + self.assertEqual(univ.Null(""), kwa['parameters']) + + eci = asn1Object['content']['encryptedContentInfo'] + cea = eci['contentEncryptionAlgorithm'] + self.assertEqual(rfc3058.id_IDEA_CBC, cea['algorithm']) + + iv = univ.OctetString(hexValue='424f4755535f4956') + self.assertEqual(iv, cea['parameters']['iv']) + +class SMIMECapabilitiesTestCase(unittest.TestCase): + smime_capabilities_pem_text = "MB4wDQYLKwYBBAGBPAcBAQIwDQYLKwYBBAGBPAcBAQY=" + + def setUp(self): + self.asn1Spec = rfc5751.SMIMECapabilities() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.smime_capabilities_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + alg_oid_list = [ ] + for cap in asn1Object: + self.assertFalse(cap['parameters'].hasValue()) + alg_oid_list.append(cap['capabilityID']) + + self.assertIn(rfc3058.id_IDEA_CBC, alg_oid_list) + self.assertIn(rfc3058.id_alg_CMSIDEAwrap, alg_oid_list) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc3114.py b/tests/test_rfc3114.py new file mode 100644 index 0000000..d0492a6 --- /dev/null +++ b/tests/test_rfc3114.py @@ -0,0 +1,244 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc3114 +from pyasn1_modules import rfc5035 +from pyasn1_modules import rfc5083 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5755 + + +class SecurityLabelTestCase(unittest.TestCase): + pem_text = """\ +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 +bXBsZS5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQ9/m9uACpsTl2frBuILHiw +IJyfUEpKseYJ+JYL1AtIZU0YeJ9DA+32h0ZeNGJDtDClnbBEPpn3W/5+TzldcsTe +QlAJB08gcVRjkQym9LtPq7rGubCeVWlRRE9M7F9znk6jggGtMIIBqTAdBgNVHQ4E +FgQUJuolDwsyICik11oKjf8t3L1/VGUwbwYDVR0jBGgwZoAU8jXbNATapVXyvWkD +mbBi7OIVCMGhQ6RBMD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UE +BwwHSGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0GCCQDokdYGkU/O8jAPBgNVHRMB +Af8EBTADAQH/MAsGA1UdDwQEAwIBhjBCBglghkgBhvhCAQ0ENRYzVGhpcyBjZXJ0 +aWZpY2F0ZSBjYW5ub3QgYmUgdHJ1c3RlZCBmb3IgYW55IHB1cnBvc2UuMBUGA1Ud +IAQOMAwwCgYIKwYBBQUHDQIwCgYDVR02BAMCAQIwgZEGCCsGAQUFBwEVBIGEMIGB +MFkGCyqGSIb3DQEJEAcDAwIF4DFGMESACyqGSIb3DQEJEAcEgTUwMwwXTEFXIERF +UEFSVE1FTlQgVVNFIE9OTFkMGEhVTUFOIFJFU09VUkNFUyBVU0UgT05MWTARBgsq +hkiG9w0BCRAHAgMCBPAwEQYLKoZIhvcNAQkQBwEDAgXgMAoGCCqGSM49BAMDA2cA +MGQCMBlIP4FWrNzWXR8OgfcvCLGPG+110EdsmwznIF6ThT1vbJYvYoSbBXTZ9OCh +/cCMMQIwJOySybHl/eLkNJh971DWF4mUQkt3WGBmZ+9Rg2cJTdat2ZjPKg101NuD +tkUyjGxfMIID1DCCA1qgAwIBAgIUUc1IQGJpeYQ0XwOS2ZmVEb3aeZ0wCgYIKoZI +zj0EAwMwZjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlZBMRAwDgYDVQQHEwdIZXJu +ZG9uMRAwDgYDVQQKEwdFeGFtcGxlMQwwCgYDVQQLEwNQQ0ExGDAWBgNVBAMTD3Bj +YS5leGFtcGxlLmNvbTAeFw0xOTExMDUyMjIwNDZaFw0yMDExMDQyMjIwNDZaMIGS +MQswCQYDVQQGEwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xEDAO +BgNVBAoTB0V4YW1wbGUxIjAgBgNVBAsTGUh1bWFuIFJlc291cmNlIERlcGFydG1l +bnQxDTALBgNVBAMTBEZyZWQxHzAdBgkqhkiG9w0BCQEWEGZyZWRAZXhhbXBsZS5j +b20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQObFslQ2EBP0xlDJ3sRnsNaqm/woQg +KpBispSxXxK5bWUVpfnWsZnjLWhtDuPcu1BcBlM2g7gwL/aw8nUSIK3D8Ja9rTUQ +QXc3zxnkcl8+8znNXHMGByRjPUH87C+TOrqjggGaMIIBljAdBgNVHQ4EFgQU5m71 +1OqFDNGRSWMOSzTXjpTLIFUwbwYDVR0jBGgwZoAUJuolDwsyICik11oKjf8t3L1/ +VGWhQ6RBMD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVy +bmRvbjERMA8GA1UECgwIQm9ndXMgQ0GCCQCls1QoG7BuRjAPBgNVHRMBAf8EBTAD +AQH/MAsGA1UdDwQEAwIBhjBCBglghkgBhvhCAQ0ENRYzVGhpcyBjZXJ0aWZpY2F0 +ZSBjYW5ub3QgYmUgdHJ1c3RlZCBmb3IgYW55IHB1cnBvc2UuMBUGA1UdIAQOMAww +CgYIKwYBBQUHDQIwCgYDVR02BAMCAQIwfwYDVR0JBHgwdjBJBgNVBDcxQjBABgsq +hkiG9w0BCRAHAwMCBeAxLTArgAsqhkiG9w0BCRAHBIEcMBoMGEhVTUFOIFJFU09V +UkNFUyBVU0UgT05MWTApBglghkgBZQIBBUQxHAwaSHVtYW4gUmVzb3VyY2VzIERl +cGFydG1lbnQwCgYIKoZIzj0EAwMDaAAwZQIwVh/RypULFgPpAN0I7OvuMomRWnm/ +Hea3Hk8PtTRz2Zai8iYat7oeAmGVgMhSXy2jAjEAuJW4l/CFatBy4W/lZ7gS3weB +dBa5WEDIFFMC7GjGtCeLtXYqWfBnRdK26dOaHLB2MYIB7jCCAeoCAQEwfjBmMQsw +CQYDVQQGEwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xEDAOBgNV +BAoTB0V4YW1wbGUxDDAKBgNVBAsTA1BDQTEYMBYGA1UEAxMPcGNhLmV4YW1wbGUu +Y29tAhRRzUhAYml5hDRfA5LZmZURvdp5nTALBglghkgBZQMEAgKggeIwGgYJKoZI +hvcNAQkDMQ0GCyqGSIb3DQEJEAEXMBwGCSqGSIb3DQEJBTEPFw0xOTExMDgyMDA4 +MzFaMD8GCSqGSIb3DQEJBDEyBDCd5WyvIB0VdXgPBWPtI152MIJLg5o68IRimCXx +bVY0j3YyAKbi0egiZ/UunkyCfv0wZQYLKoZIhvcNAQkQAgIxVjFUAgEIBgsqhkiG +9w0BCRAHAzEtMCuACyqGSIb3DQEJEAcEgRwwGgwYSFVNQU4gUkVTT1VSQ0VTIFVT +RSBPTkxZExNCb2FndXMgUHJpdmFjeSBNYXJrMAoGCCqGSM49BAMDBGcwZQIwWkD7 +03QoNrKL5HJnuGJqvML1KlUXZDHnFpnJ+QMzXi8gocyfpRXWm6h0NjXieE0XAjEA +uuDSOoaUIz+G9aemAE0ldpo1c0avNGa7BtynUTHmwosD6Sjfj0epAg9OnMedOjbr +""" + + def testDerCodec(self): + layers = { } + layers.update(rfc5652.cmsContentTypesMap) + + getNextLayer = { + rfc5652.id_ct_contentInfo: lambda x: x['contentType'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContentType'], + rfc5083.id_ct_authEnvelopedData: lambda x: None + } + + getNextSubstrate = { + rfc5652.id_ct_contentInfo: lambda x: x['content'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContent'], + rfc5083.id_ct_authEnvelopedData: lambda x: None + } + + substrate = pem.readBase64fromText(self.pem_text) + + next_layer = rfc5652.id_ct_contentInfo + while next_layer: + asn1Object, rest = der_decoder(substrate, asn1Spec=layers[next_layer]) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + if next_layer == rfc5652.id_signedData: + attrs = asn1Object['signerInfos'][0]['signedAttrs'] + certs = asn1Object['certificates'] + + substrate = getNextSubstrate[next_layer](asn1Object) + next_layer = getNextLayer[next_layer](asn1Object) + + spid = rfc3114.id_tsp_TEST_Whirlpool + catid = rfc3114.id_tsp_TEST_Whirlpool_Categories + conf = rfc3114.Whirlpool_SecurityClassification(value='whirlpool-confidential') + + self.assertIn(catid, rfc5755.securityCategoryMap) + self.assertIn(rfc5755.id_at_clearance, rfc5280.certificateAttributesMap) + self.assertIn(rfc5280.id_ce_subjectDirectoryAttributes, rfc5280.certificateExtensionsMap) + + security_label_okay = False + + for attr in attrs: + if attr['attrType'] == rfc5035.id_aa_securityLabel: + esssl, rest = der_decoder( + attr['attrValues'][0], asn1Spec=rfc5035.ESSSecurityLabel()) + + self.assertFalse(rest) + self.assertTrue(esssl.prettyPrint()) + self.assertEqual(attr['attrValues'][0], der_encoder(esssl)) + + self.assertEqual(spid, esssl['security-policy-identifier']) + self.assertEqual(conf, esssl['security-classification']) + + for cat in esssl['security-categories']: + if cat['type'] == catid: + scv, rest = der_decoder( + cat['value'], asn1Spec=rfc3114.SecurityCategoryValues()) + + self.assertFalse(rest) + self.assertTrue(scv.prettyPrint()) + self.assertEqual(cat['value'], der_encoder(scv)) + + for scv_str in scv: + self.assertIn('USE ONLY', scv_str) + security_label_okay = True + + self.assertTrue(security_label_okay) + + clearance_okay = False + for cert_choice in certs: + for extn in cert_choice['certificate']['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectDirectoryAttributes: + ev, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertFalse(rest) + self.assertTrue(ev.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(ev)) + + for attr in ev: + + if attr['type'] == rfc5755.id_at_clearance: + av, rest = der_decoder( + attr['values'][0], + asn1Spec=rfc5280.certificateAttributesMap[attr['type']]) + + self.assertEqual(spid, av['policyId']) + + for cat in av['securityCategories']: + + self.assertEqual(catid, cat['type']) + + scv, rest = der_decoder( + cat['value'], + asn1Spec=rfc5755.securityCategoryMap[cat['type']]) + + self.assertFalse(rest) + self.assertTrue(scv.prettyPrint()) + self.assertEqual(cat['value'], der_encoder(scv)) + + for scv_str in scv: + self.assertIn('USE ONLY', scv_str) + clearance_okay = True + + self.assertTrue(clearance_okay) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc3125.py b/tests/test_rfc3125.py new file mode 100644 index 0000000..d7072b9 --- /dev/null +++ b/tests/test_rfc3125.py @@ -0,0 +1,109 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc2985 +from pyasn1_modules import rfc3125 + + +class SignaturePolicyTestCase(unittest.TestCase): + pem_text = """\ +MIIMYzALBglghkgBZQMEAgEwggwwBgorgR6RmYQFAQICGA8yMDE2MTAwMjAwMDAwMFowgaSk +XjBcMQswCQYDVQQGEwJTSzETMBEGA1UEBwwKQnJhdGlzbGF2YTEiMCAGA1UECgwZTmFyb2Ru +eSBiZXpwZWNub3N0bnkgdXJhZDEUMBIGA1UECwwLU2VrY2lhIElCRVCGQmh0dHA6Ly9lcC5u +YnVzci5zay90cnVzdGVkX2RhdGEvMjAxNjEwMDIwMDAwMDB6c2lnbmF0dXJlcG9saWN5LmRl +cgyBz0VOOiBFbC4gc2lnbmF0dXJlL3NlYWwsIG9wdGlvbmFsIGVsLiB0aW1lLXN0YW1wIG92 +ZXIgT0NTUCwgYWNjb3JkaW5nIHRvIFJlZ3VsYXRpb24gKEVVKSBObyA5MTAvMjAxNC4gU0s6 +IEVsLiBwb2RwaXMvcGXEjWHFpSwgdm9saXRlxL5uw6EgZWwuIMSNYXNvdsOhIHBlxI1pYXRr +YSBuYWQgT0NTUCwgcG9kxL5hIG5hcmlhZGVuaWEgKEXDmikgxI0uIDkxMC8yMDE0LjCCCpYw +IhgPMjAxNjEwMDIwMDAwMDBaGA8yMDIxMTAwMjAwMDAwMFowggpsoD8wPTA3MC4GCSqGSIb3 +DQEJAwYJKoZIhvcNAQkEBgkqhkiG9w0BCQUGCyqGSIb3DQEJEAIvMAChAwoBAjACMACiEjAQ +ow4wDAIBAAIBAAIBAAIBAaSCChMwggoPoIIB/zCCAfswCwYJYIZIAWUDBAIBMAsGCWCGSAFl +AwQCAjALBglghkgBZQMEAgMwCwYJYIZIAWUDBAIGMAsGCWCGSAFlAwQCCDALBglghkgBZQME +AgkwCwYJYIZIAWUDBAIKMA8GCWCGSAFlAwQDAgICCAAwDwYJYIZIAWUDBAMDAgIIADAPBglg +hkgBZQMEAwQCAggAMA8GCWCGSAFlAwQDBgICCAAwDwYJYIZIAWUDBAMHAgIIADAPBglghkgB +ZQMEAwgCAggAMA4GCCqGSM49BAMCAgIBADAOBggqhkjOPQQDAwICAQAwDgYIKoZIzj0EAwQC +AgEAMA8GCWCGSAFlAwQDCgICAQAwDwYJYIZIAWUDBAMLAgIBADAPBglghkgBZQMEAwwCAgEA +MA8GCSqGSIb3DQEBCwICCAAwDwYJKoZIhvcNAQEMAgIIADAPBgkqhkiG9w0BAQ0CAggAMA8G +CWCGSAFlAwQDDgICCAAwDwYJYIZIAWUDBAMPAgIIADAPBglghkgBZQMEAxACAggAMA8GCSqG +SIb3DQEBCgICCAAwDwYJKoZIhvcNAQEBAgIIADANBgcqhkjOPQIBAgIBADAOBggrJAMDAgUC +AQICAQAwDgYIKyQDAwIFBAQCAgEAMA4GCCskAwMCBQQFAgIBADAOBggrJAMDAgUEBgICAQCh +ggH/MIIB+zALBglghkgBZQMEAgEwCwYJYIZIAWUDBAICMAsGCWCGSAFlAwQCAzALBglghkgB +ZQMEAgYwCwYJYIZIAWUDBAIIMAsGCWCGSAFlAwQCCTALBglghkgBZQMEAgowDwYJYIZIAWUD +BAMCAgIIADAPBglghkgBZQMEAwMCAggAMA8GCWCGSAFlAwQDBAICCAAwDwYJYIZIAWUDBAMG +AgIIADAPBglghkgBZQMEAwcCAggAMA8GCWCGSAFlAwQDCAICCAAwDgYIKoZIzj0EAwICAgEA +MA4GCCqGSM49BAMDAgIBADAOBggqhkjOPQQDBAICAQAwDwYJYIZIAWUDBAMKAgIBADAPBglg +hkgBZQMEAwsCAgEAMA8GCWCGSAFlAwQDDAICAQAwDwYJKoZIhvcNAQELAgIIADAPBgkqhkiG +9w0BAQwCAggAMA8GCSqGSIb3DQEBDQICCAAwDwYJYIZIAWUDBAMOAgIIADAPBglghkgBZQME +Aw8CAggAMA8GCWCGSAFlAwQDEAICCAAwDwYJKoZIhvcNAQEKAgIIADAPBgkqhkiG9w0BAQEC +AggAMA0GByqGSM49AgECAgEAMA4GCCskAwMCBQIBAgIBADAOBggrJAMDAgUEBAICAQAwDgYI +KyQDAwIFBAUCAgEAMA4GCCskAwMCBQQGAgIBAKKCAf8wggH7MAsGCWCGSAFlAwQCATALBglg +hkgBZQMEAgIwCwYJYIZIAWUDBAIDMAsGCWCGSAFlAwQCBjALBglghkgBZQMEAggwCwYJYIZI +AWUDBAIJMAsGCWCGSAFlAwQCCjAPBglghkgBZQMEAwICAggAMA8GCWCGSAFlAwQDAwICCAAw +DwYJYIZIAWUDBAMEAgIIADAPBglghkgBZQMEAwYCAggAMA8GCWCGSAFlAwQDBwICCAAwDwYJ +YIZIAWUDBAMIAgIIADAOBggqhkjOPQQDAgICAQAwDgYIKoZIzj0EAwMCAgEAMA4GCCqGSM49 +BAMEAgIBADAPBglghkgBZQMEAwoCAgEAMA8GCWCGSAFlAwQDCwICAQAwDwYJYIZIAWUDBAMM +AgIBADAPBgkqhkiG9w0BAQsCAggAMA8GCSqGSIb3DQEBDAICCAAwDwYJKoZIhvcNAQENAgII +ADAPBglghkgBZQMEAw4CAggAMA8GCWCGSAFlAwQDDwICCAAwDwYJYIZIAWUDBAMQAgIIADAP +BgkqhkiG9w0BAQoCAggAMA8GCSqGSIb3DQEBAQICCAAwDQYHKoZIzj0CAQICAQAwDgYIKyQD +AwIFAgECAgEAMA4GCCskAwMCBQQEAgIBADAOBggrJAMDAgUEBQICAQAwDgYIKyQDAwIFBAYC +AgEAo4IB/zCCAfswCwYJYIZIAWUDBAIBMAsGCWCGSAFlAwQCAjALBglghkgBZQMEAgMwCwYJ +YIZIAWUDBAIGMAsGCWCGSAFlAwQCCDALBglghkgBZQMEAgkwCwYJYIZIAWUDBAIKMA8GCWCG +SAFlAwQDAgICCAAwDwYJYIZIAWUDBAMDAgIIADAPBglghkgBZQMEAwQCAggAMA8GCWCGSAFl +AwQDBgICCAAwDwYJYIZIAWUDBAMHAgIIADAPBglghkgBZQMEAwgCAggAMA4GCCqGSM49BAMC +AgIBADAOBggqhkjOPQQDAwICAQAwDgYIKoZIzj0EAwQCAgEAMA8GCWCGSAFlAwQDCgICAQAw +DwYJYIZIAWUDBAMLAgIBADAPBglghkgBZQMEAwwCAgEAMA8GCSqGSIb3DQEBCwICCAAwDwYJ +KoZIhvcNAQEMAgIIADAPBgkqhkiG9w0BAQ0CAggAMA8GCWCGSAFlAwQDDgICCAAwDwYJYIZI +AWUDBAMPAgIIADAPBglghkgBZQMEAxACAggAMA8GCSqGSIb3DQEBCgICCAAwDwYJKoZIhvcN +AQEBAgIIADANBgcqhkjOPQIBAgIBADAOBggrJAMDAgUCAQICAQAwDgYIKyQDAwIFBAQCAgEA +MA4GCCskAwMCBQQFAgIBADAOBggrJAMDAgUEBgICAQCkggH/MIIB+zALBglghkgBZQMEAgEw +CwYJYIZIAWUDBAICMAsGCWCGSAFlAwQCAzALBglghkgBZQMEAgYwCwYJYIZIAWUDBAIIMAsG +CWCGSAFlAwQCCTALBglghkgBZQMEAgowDwYJYIZIAWUDBAMCAgIIADAPBglghkgBZQMEAwMC +AggAMA8GCWCGSAFlAwQDBAICCAAwDwYJYIZIAWUDBAMGAgIIADAPBglghkgBZQMEAwcCAggA +MA8GCWCGSAFlAwQDCAICCAAwDgYIKoZIzj0EAwICAgEAMA4GCCqGSM49BAMDAgIBADAOBggq +hkjOPQQDBAICAQAwDwYJYIZIAWUDBAMKAgIBADAPBglghkgBZQMEAwsCAgEAMA8GCWCGSAFl +AwQDDAICAQAwDwYJKoZIhvcNAQELAgIIADAPBgkqhkiG9w0BAQwCAggAMA8GCSqGSIb3DQEB +DQICCAAwDwYJYIZIAWUDBAMOAgIIADAPBglghkgBZQMEAw8CAggAMA8GCWCGSAFlAwQDEAIC +CAAwDwYJKoZIhvcNAQEKAgIIADAPBgkqhkiG9w0BAQECAggAMA0GByqGSM49AgECAgEAMA4G +CCskAwMCBQIBAgIBADAOBggrJAMDAgUEBAICAQAwDgYIKyQDAwIFBAUCAgEAMA4GCCskAwMC +BQQGAgIBADAABCAaWobQZ1EuANtF/NjfuaBXR0nR0fKnGJ7Z8t/mregtvQ== +""" + + def setUp(self): + self.asn1Spec = rfc3125.SignaturePolicy() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + svp = asn1Object['signPolicyInfo']['signatureValidationPolicy'] + sr = svp['commonRules']['signerAndVeriferRules']['signerRules'] + msa = sr['mandatedSignedAttr'] + + self.assertIn(rfc2985.pkcs_9_at_contentType, msa) + self.assertIn(rfc2985.pkcs_9_at_messageDigest, msa) + self.assertIn(rfc2985.pkcs_9_at_signingTime, msa) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + import sys + + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc3161.py b/tests/test_rfc3161.py new file mode 100644 index 0000000..47db88a --- /dev/null +++ b/tests/test_rfc3161.py @@ -0,0 +1,81 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc3161 + + +class TSPQueryTestCase(unittest.TestCase): + tsp_query_pem_text = """\ +MFYCAQEwUTANBglghkgBZQMEAgMFAARAGu1DauxDZZv8F7l4EKIbS00U40mUKfBW5C0giEz0 +t1zOHCvK4A8i8zxwUXFHv4pAJZE+uFhZ+v53HTg9rLjO5Q== +""" + + def setUp(self): + self.asn1Spec = rfc3161.TimeStampReq() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.tsp_query_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + +class TSPResponseTestCase(unittest.TestCase): + tsp_response_pem_text = """\ +MIIFMTADAgEAMIIFKAYJKoZIhvcNAQcCoIIFGTCCBRUCAQMxCzAJBgUrDgMCGgUAMIIBowYL +KoZIhvcNAQkQAQSgggGSBIIBjjCCAYoCAQEGBCoDBAEwUTANBglghkgBZQMEAgMFAARAGu1D +auxDZZv8F7l4EKIbS00U40mUKfBW5C0giEz0t1zOHCvK4A8i8zxwUXFHv4pAJZE+uFhZ+v53 +HTg9rLjO5QIDDwJEGA8yMDE5MDUxMDE4MzQxOFoBAf+gggERpIIBDTCCAQkxETAPBgNVBAoT +CEZyZWUgVFNBMQwwCgYDVQQLEwNUU0ExdjB0BgNVBA0TbVRoaXMgY2VydGlmaWNhdGUgZGln +aXRhbGx5IHNpZ25zIGRvY3VtZW50cyBhbmQgdGltZSBzdGFtcCByZXF1ZXN0cyBtYWRlIHVz +aW5nIHRoZSBmcmVldHNhLm9yZyBvbmxpbmUgc2VydmljZXMxGDAWBgNVBAMTD3d3dy5mcmVl +dHNhLm9yZzEiMCAGCSqGSIb3DQEJARYTYnVzaWxlemFzQGdtYWlsLmNvbTESMBAGA1UEBxMJ +V3VlcnpidXJnMQswCQYDVQQGEwJERTEPMA0GA1UECBMGQmF5ZXJuMYIDWjCCA1YCAQEwgaMw +gZUxETAPBgNVBAoTCEZyZWUgVFNBMRAwDgYDVQQLEwdSb290IENBMRgwFgYDVQQDEw93d3cu +ZnJlZXRzYS5vcmcxIjAgBgkqhkiG9w0BCQEWE2J1c2lsZXphc0BnbWFpbC5jb20xEjAQBgNV +BAcTCVd1ZXJ6YnVyZzEPMA0GA1UECBMGQmF5ZXJuMQswCQYDVQQGEwJERQIJAMHphhYNqOmC +MAkGBSsOAwIaBQCggYwwGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJ +BTEPFw0xOTA1MTAxODM0MThaMCMGCSqGSIb3DQEJBDEWBBSuLICty7PQHx0Ynk0a3rGcCRrf +EjArBgsqhkiG9w0BCRACDDEcMBowGDAWBBSRbaPYYOzKguNLxZ0Xk+fpaIdfFDANBgkqhkiG +9w0BAQEFAASCAgBFDVbGQ3L5GcaUBMtBnMW7x3S57QowQhhrTewvncY+3Nc2i6tlM1UEdxIp +3m2iMqaH/N2xIm2sU/L/lIwaT1XIS4bJ2Nn8UPjZu/prJrVUFTMjJ5LWkG55x6c5A4pa2xxS +N/kOV2e+6RHYlGvcDOvu2fzuz08hE+NjaHIPg3idU1cBsl0gTWZCTrxdXTLuuvHahxUAdQKm +gTdGPjIiOR4GYpaVxEAgulaBQLZU5MhfBTASI1LkljhiFeDBQMhTUeZoA59/OxgnQR1Zpca4 +ZuWuqnZImxziRQA1tX/6pjAo5eP1V+SLWYHeIO7ia/urGIK9AXd3jY3Ljq4h7R1E+RRKIseO +74mmtbJtCaiGL9H+6k164qC7U5fHBzKl3UboZtOUmNj10IJPUNyKQ5JPwCe6HEhbeXLRdh/8 +bjdqy56hBHyG1NRBqiTXTvj9LOzsJGIF5GjwyCT0B2hpvzdTdzNtfQ27HUUYgnYg0fGEpNpi +vyaW5qCh9S704IKB0m/fXlqiIfNVdqDr/aAHNww8CouZP2oFO61WXCspbFNPLubeqxd5P4o4 +dJzD4PKsurILdX7SL8pRI+O2UtJLwNB1t3LBLKfTZuOWoSBFvQwbqBsDEchrZIDZXSXMbXd6 +uuvuO3ZsRWuej+gso+nWi3CRnRc9Wb0++cq4s8YSLaYSj2pHMA== +""" + + def setUp(self): + self.asn1Spec = rfc3161.TimeStampResp() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.tsp_response_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc3274.py b/tests/test_rfc3274.py new file mode 100644 index 0000000..cb24d37 --- /dev/null +++ b/tests/test_rfc3274.py @@ -0,0 +1,81 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc3274 +from pyasn1_modules import rfc5652 + + +class CompressedDataTestCase(unittest.TestCase): + compressed_data_pem_text = """\ +MIIB7wYLKoZIhvcNAQkQAQmgggHeMIIB2gIBADANBgsqhkiG9w0BCRADCDCCAcQG +CSqGSIb3DQEHAaCCAbUEggGxeJxVksGO1DAQRO/+ir4xK4VlNSAhcUPRrgRiLgw/ +0Il7Egu7bdntMOHraSezMJyixOWq19XpIwuxvP2xJvoEQld5lzw6Nub7Sw/vjx8/ +dJDq4F2ZyYJj+FqZ4Pj0dOzA0sUxFUC4xBxQ2gNqcTzBGEPKVApZY1EQsKn6vCaJ +U8Y0uxFOeowTwXllwSsc+tP5Qe9tOCCK8wjQ32zUcvcZSDMIJCOX4PQgMqQcF2c3 +Dq5hoAzxAmgXVN+JSqfUo6+2YclMhrwLjlHaVRVutplsZYs8rvBL2WblqN7CTD4B +MqAIjj8pd1ASUXMyNbXccWeDYd0sxlsGYIhVp3i1l6jgr3qtUeUehbIpQqnAoVSN +1IqKm7hZaI3EY2tLIR86RbD//ONCGb2HsPdnivvdqvrsZY51mlu+NjTjQhpKWz0p +FvRlWw9ae7+fVgKKie0SeFpIZYemoyuG5HUS2QY6fTk9N6zz+dsuUyr9Xghs5Ddi +1LbZbVoNHDyFNv19jL7qiv9uuLK/XTD3Kqct1JS822vS8vWXpMzYBtal/083rMap +XQ7u2qbaKFtZ7V96NH8ApkUFkg== +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.compressed_data_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc3274.id_ct_compressedData, asn1Object['contentType']) + + cd, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc3274.CompressedData()) + + self.assertFalse(rest) + self.assertTrue(cd.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(cd)) + + self.assertEqual(rfc3274.id_alg_zlibCompress, + cd['compressionAlgorithm']['algorithm']) + self.assertEqual(rfc5652.id_data, cd['encapContentInfo']['eContentType']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.compressed_data_pem_text) + asn1Object, rest = der_decoder(substrate, + asn1Spec=self.asn1Spec, + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual( + rfc3274.id_ct_compressedData, asn1Object['contentType']) + + cd = asn1Object['content'] + + self.assertEqual(rfc3274.id_alg_zlibCompress, + cd['compressionAlgorithm']['algorithm']) + self.assertEqual(rfc5652.id_data, cd['encapContentInfo']['eContentType']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc3279.py b/tests/test_rfc3279.py new file mode 100644 index 0000000..210a2e9 --- /dev/null +++ b/tests/test_rfc3279.py @@ -0,0 +1,385 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc3279 + + +class RSACertificateTestCase(unittest.TestCase): + rsa_cert_pem_text = """\ +MIIE8TCCA9mgAwIBAgIQbyXcFa/fXqMIVgw7ek/H+DANBgkqhkiG9w0BAQUFADBv +MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk +ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF +eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow +gYExCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO +BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMScwJQYD +VQQDEx5DT01PRE8gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDQQIuLcuORG/dRwRtUBJjTqb/B5opdO4f7u4jO +DeMvPwaW8KIpUJmu2zuhV7B0UXHN7UKRTUH+qcjYaoZ3RLtZZpdQXrTULHBEz9o3 +lUJpPDDEcbNS8CFNodi6OXwcnqMknfKDFpiqFnxDmxVbt640kf7UYiYYRpo/68H5 +8ZBX66x6DYvbcjBqZtXgRqNw3GjZ/wRIiXfeten7Z21B6bw5vTLZYgLxsag9bjec +4i/i06Imi8a4VUOI4SM+pdIkOWpHqwDUobOpJf4NP6cdutNRwQuk2qw471VQJAVl +RpM0Ty2NrcbUIRnSjsoFYXEHc0flihkSvQRNzk6cpUisuyb3AgMBAAGjggF0MIIB +cDAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTvA73gJMtUGjAdBgNVHQ4EFgQUC1jl +i8ZMFTekQKkwqSG+RzZaVv8wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB +Af8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9j +cmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4dGVybmFsQ0FSb290LmNybDCBswYI +KwYBBQUHAQEEgaYwgaMwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0 +LmNvbS9BZGRUcnVzdEV4dGVybmFsQ0FSb290LnA3YzA5BggrBgEFBQcwAoYtaHR0 +cDovL2NydC51c2VydHJ1c3QuY29tL0FkZFRydXN0VVROU0dDQ0EuY3J0MCUGCCsG +AQUFBzABhhlodHRwOi8vb2NzcC51c2VydHJ1c3QuY29tMA0GCSqGSIb3DQEBBQUA +A4IBAQAHYJOZqs7Q00fQNzPeP2S35S6jJQzVMx0Njav2fkZ7WQaS44LE5/X289kF +z0k0LTdf9CXH8PtrI3fx8UDXTLtJRTHdAChntylMdagfeTHJNjcPyjVPjPF+3vxG +q79om3AjMC63xVx7ivsYE3lLkkKM3CyrbCK3KFOzGkrOG/soDrc6pNoN90AyT99v +uwFQ/IfTdtn8+7aEA8rJNhj33Wzbu7qBHKat/ij5z7micV0ZBepKRtxzQe+JlEKx +Q4hvNRevHmCDrHqMEHufyfaDbZ76iO4+3e6esL/garnQnweyCROa9aTlyFt5p0c1 +M2jlVZ6qW8swC53HD79oRIGXi1FK +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.rsa_cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + spki_a = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + + self.assertEqual(rfc3279.rsaEncryption, spki_a['algorithm']) + + spki_pk = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'].asOctets() + pk, rest = der_decoder(spki_pk, asn1Spec=rfc3279.RSAPublicKey()) + + self.assertFalse(rest) + self.assertTrue(pk.prettyPrint()) + self.assertEqual(spki_pk, der_encoder(pk)) + self.assertEqual(65537, pk['publicExponent']) + self.assertEqual(rfc3279.sha1WithRSAEncryption, + asn1Object['tbsCertificate']['signature']['algorithm']) + self.assertEqual(rfc3279.sha1WithRSAEncryption, + asn1Object['signatureAlgorithm']['algorithm']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.rsa_cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + spki_a = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + + self.assertEqual(rfc3279.rsaEncryption, spki_a['algorithm']) + self.assertEqual(univ.Null(""), spki_a['parameters']) + + +class ECCertificateTestCase(unittest.TestCase): + ec_cert_pem_text = """\ +MIIDrDCCApSgAwIBAgIQCssoukZe5TkIdnRw883GEjANBgkqhkiG9w0BAQwFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0xMzAzMDgxMjAwMDBaFw0yMzAzMDgxMjAwMDBaMEwxCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJjAkBgNVBAMTHURpZ2lDZXJ0IEVDQyBT +ZWN1cmUgU2VydmVyIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE4ghC6nfYJN6g +LGSkE85AnCNyqQIKDjc/ITa4jVMU9tWRlUvzlgKNcR7E2Munn17voOZ/WpIRllNv +68DLP679Wz9HJOeaBy6Wvqgvu1cYr3GkvXg6HuhbPGtkESvMNCuMo4IBITCCAR0w +EgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwNAYIKwYBBQUHAQEE +KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQgYDVR0f +BDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xv +YmFsUm9vdENBLmNybDA9BgNVHSAENjA0MDIGBFUdIAAwKjAoBggrBgEFBQcCARYc +aHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAdBgNVHQ4EFgQUo53mH/naOU/A +buiRy5Wl2jHiCp8wHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJ +KoZIhvcNAQEMBQADggEBAMeKoENL7HTJxavVHzA1Nm6YVntIrAVjrnuaVyRXzG/6 +3qttnMe2uuzO58pzZNvfBDcKAEmzP58mrZGMIOgfiA4q+2Y3yDDo0sIkp0VILeoB +UEoxlBPfjV/aKrtJPGHzecicZpIalir0ezZYoyxBEHQa0+1IttK7igZFcTMQMHp6 +mCHdJLnsnLWSB62DxsRq+HfmNb4TDydkskO/g+l3VtsIh5RHFPVfKK+jaEyDj2D3 +loB5hWp2Jp2VDCADjT7ueihlZGak2YPqmXTNbk19HOuNssWvFhtOyPNV6og4ETQd +Ea8/B6hPatJ0ES8q/HO3X8IVQwVs1n3aAr0im0/T+Xc= +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.ec_cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + spki_a = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + + self.assertEqual(rfc3279.id_ecPublicKey, spki_a['algorithm']) + + spki_a_p, rest = der_decoder( + spki_a['parameters'], asn1Spec=rfc3279.EcpkParameters()) + + self.assertFalse(rest) + self.assertTrue(spki_a_p.prettyPrint()) + self.assertEqual(spki_a['parameters'], der_encoder(spki_a_p)) + self.assertEqual(univ.ObjectIdentifier('1.3.132.0.34'), spki_a_p['namedCurve']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.ec_cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + spki_a = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + + self.assertEqual(rfc3279.id_ecPublicKey, spki_a['algorithm']) + self.assertEqual( + univ.ObjectIdentifier('1.3.132.0.34'), spki_a['parameters']['namedCurve']) + + +class DSACertificateTestCase(unittest.TestCase): + dsa_cert_pem_text = """\ +MIIDpjCCA0ygAwIBAgIUY8xt3l0B9nIPWSpjs0hDJUJZmCkwCwYJYIZIAWUDBAMC +MD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJWQTEQMA4GA1UEBxMHSGVybmRvbjER +MA8GA1UEChMIQm9ndXMgQ0EwHhcNMTkxMDIwMjAxMjMwWhcNMjAxMDE5MjAxMjMw +WjBwMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24x +EDAOBgNVBAoTB0V4YW1wbGUxDjAMBgNVBAsTBUFsaWNlMSAwHgYJKoZIhvcNAQkB +FhFhbGljZUBleGFtcGxlLmNvbTCCAbYwggErBgcqhkjOOAQBMIIBHgKBgQCLpR53 +xHfe+SiknAK/L9lm/ZO1109c9iYkriPIW/5MMlM+qc/tdRkKpG6ELIpfXTPtKCJm +zqqVIyTmAJryyE8Xw0Ie2mzYPU5ULvKmllQkjTsWgPGgQBkciZ0AW9ggD9VwZilg +4qh3iSO7T97hVQFnpCh6vm8pOH6UP/5kpr9ZJQIVANzdbztBJlJfqCB1t4h/NvSu +wCFvAoGAITP+jhYk9Rngd98l+5ccgauQ+cLEUBgNG2Wq56zBXQbLou6eKkQi7ecL +NiRmExq3IU3LOj426wSxL72Kw6FPyOEv3edIFkJJEHL4Z+ZJeVe//dzya0ddOJ7k +k6qNF2ic+viD/5Vm8yRyKiig2uHH/MgIesLdZnvbzvX+f/P0z50DgYQAAoGALAUl +jkOi1PxjjFVvhGfK95yIsrfbfcIEKUBaTs9NR2rbGWUeP+93paoXwP39X9wrJx2M +SWeHWhWKszNgoiyqYT0k4R9mem3WClotxOvB5fHfwIp2kQYvE7H0/TPdGhfUpHQG +YpyLQgT6L80meSKMFnu4VXGzOANhWDxu3JxiADCjgZQwgZEwCwYDVR0PBAQDAgeA +MEIGCWCGSAGG+EIBDQQ1FjNUaGlzIGNlcnRpZmljYXRlIGNhbm5vdCBiZSB0cnVz +dGVkIGZvciBhbnkgcHVycG9zZS4wHQYDVR0OBBYEFO37wHcauyc03rDc6cDRRsHz +gcK+MB8GA1UdIwQYMBaAFM1IZQGDsqYHWwb+I4EMxHPk0bU4MAsGCWCGSAFlAwQD +AgNHADBEAiBBRbfMzLi7+SVyO8SM3xxwUsMf/k1B+Nkvf1kBTfCfGwIgSAx/6mI+ +pNqdXqZZGESXy1MT1aBc4ynPGLFUr2r7cPY= +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.dsa_cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + spki_a = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + + self.assertEqual(rfc3279.id_dsa, spki_a['algorithm']) + + spki_a_p, rest = der_decoder(spki_a['parameters'], + asn1Spec=rfc3279.Dss_Parms()) + self.assertFalse(rest) + self.assertTrue(spki_a_p.prettyPrint()) + self.assertEqual(spki_a['parameters'], der_encoder(spki_a_p)) + + q_value = 1260916123897116834511257683105158021801897369967 + + self.assertEqual(q_value, spki_a_p['q']) + + sig_value, rest = der_decoder( + asn1Object['signature'].asOctets(), asn1Spec=rfc3279.Dss_Sig_Value()) + + self.assertFalse(rest) + self.assertTrue(sig_value.prettyPrint()) + self.assertEqual(asn1Object['signature'].asOctets(), der_encoder(sig_value)) + self.assertTrue(sig_value['r'].hasValue()) + self.assertTrue(sig_value['s'].hasValue()) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.dsa_cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + spki_a = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + + self.assertEqual(rfc3279.id_dsa, spki_a['algorithm']) + + q_value = 1260916123897116834511257683105158021801897369967 + + self.assertEqual(q_value, spki_a['parameters']['q']) + + +class KEACertificateTestCase(unittest.TestCase): + kea_cert_pem_text = """\ +MIICizCCAjOgAwIBAgIUY8xt3l0B9nIPWSpjs0hDJUJZmCgwCQYHKoZIzjgEAzA/ +MQswCQYDVQQGEwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xETAP +BgNVBAoTCEJvZ3VzIENBMB4XDTE5MTAyMDIwMDkyMVoXDTIwMTAxOTIwMDkyMVow +cDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlZBMRAwDgYDVQQHEwdIZXJuZG9uMRAw +DgYDVQQKEwdFeGFtcGxlMQ4wDAYDVQQDEwVBbGljZTEgMB4GCSqGSIb3DQEJARYR +YWxpY2VAZXhhbXBsZS5jb20wgaAwFwYJYIZIAWUCAQEWBApc+PEn5ladbYizA4GE +AAKBgB9Lc2QcoSW0E9/VnQ2xGBtpYh9MaDUBzIixbN8rhDwh0BBesD2TwHjzBpDM +2PJ6DD1ZbBcz2M3vJaIKoZ8hA2EUtbbHX1BSnVfAdeqr5St5gfnuxSdloUjLQlWO +rOYfpFVEp6hJoKAZiYfiXz0fohNXn8+fiU5k214byxlCPlU0o4GUMIGRMAsGA1Ud +DwQEAwIDCDBCBglghkgBhvhCAQ0ENRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5ub3Qg +YmUgdHJ1c3RlZCBmb3IgYW55IHB1cnBvc2UuMB0GA1UdDgQWBBSE49bkPB9sQm27 +Rs2jgAPMyY6UCDAfBgNVHSMEGDAWgBTNSGUBg7KmB1sG/iOBDMRz5NG1ODAJBgcq +hkjOOAQDA0cAMEQCIE9PWhUbnJVdNQcVYSc36BMZ+23uk2ITLsgSXtkScF6TAiAf +TPnJ5Wym0hv2fOpnPPsWTgqvLFYfX27GGTquuOd/6A== +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.kea_cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + spki_a = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + + self.assertEqual(rfc3279.id_keyExchangeAlgorithm, spki_a['algorithm']) + + spki_a_p, rest = der_decoder(spki_a['parameters'], + asn1Spec=rfc3279.KEA_Parms_Id()) + self.assertFalse(rest) + self.assertTrue(spki_a_p.prettyPrint()) + + self.assertEqual(spki_a['parameters'], der_encoder(spki_a_p)) + self.assertEqual(univ.OctetString(hexValue='5cf8f127e6569d6d88b3'), spki_a_p) + self.assertEqual( + rfc3279.id_dsa_with_sha1, asn1Object['tbsCertificate']['signature']['algorithm']) + self.assertEqual( + rfc3279.id_dsa_with_sha1, asn1Object['signatureAlgorithm']['algorithm']) + + sig_value, rest = der_decoder(asn1Object['signature'].asOctets(), + asn1Spec=rfc3279.Dss_Sig_Value()) + self.assertFalse(rest) + self.assertTrue(sig_value.prettyPrint()) + self.assertEqual(asn1Object['signature'].asOctets(), der_encoder(sig_value)) + self.assertTrue(sig_value['r'].hasValue()) + self.assertTrue(sig_value['s'].hasValue()) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.kea_cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + spki_a = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + + self.assertEqual(rfc3279.id_keyExchangeAlgorithm, spki_a['algorithm']) + self.assertEqual( + univ.OctetString(hexValue='5cf8f127e6569d6d88b3'), spki_a['parameters']) + + self.assertEqual(rfc3279.id_dsa_with_sha1, + asn1Object['tbsCertificate']['signature']['algorithm']) + self.assertEqual( + rfc3279.id_dsa_with_sha1, asn1Object['signatureAlgorithm']['algorithm']) + + +class DHCertificateTestCase(unittest.TestCase): + dh_cert_pem_text = """\ +MIIEtDCCBFqgAwIBAgIUY8xt3l0B9nIPWSpjs0hDJUJZmCkwCwYJYIZIAWUDBAMC +MD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJWQTEQMA4GA1UEBxMHSGVybmRvbjER +MA8GA1UEChMIQm9ndXMgQ0EwHhcNMTkxMDIwMjAxMjMwWhcNMjAxMDE5MjAxMjMw +WjBwMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24x +EDAOBgNVBAoTB0V4YW1wbGUxDjAMBgNVBAsTBUFsaWNlMSAwHgYJKoZIhvcNAQkB +FhFhbGljZUBleGFtcGxlLmNvbTCCAsQwggI5BgcqhkjOPgIBMIICLAKCAQEAt9x/ +0iwGww3k19h+wbODVK1yqjFzEY2pyfXthHcn+nEw+DpURJ+iOhYPr68E3XO5sB48 +r5xTZhPN5+YejD3T8qhnDtiq4qrrSH7BOaEzqCDpHE2Bpoy3SodQ5Obaiu9Kx1ix +BRk/oRZUH+F+ATZmF0rPKrZGZOnmsh0IZm3dlmRR9FRGn0aJlZKXveqp+hZ97/r0 +cbSo6wdT47APfocgweZMvgWu1IQBs6FiunRgaeX3RyLr4fnkvCzUM7TmxpRJYtL6 +myAp007QvtgQ0AdEwVfNl3jQ0IIW7TtpXVxDDQaKZZe9yYrY4GV3etlYk8a4cpjN +rBxBCCTMASE4+iVtPQKCAQAg3m19vWc1TlHmkeqLwgvHN0Ufdyw5axWtc8qIJGZ1 +MezhyLyD4RU0VFCSocJCCe2k2kS2P2vQERZZYcn/nCYuiswCjOCbnwKozfaTZ3Fc +1KOCtb4EEcuk/th5XNhWCYJJ7Hasym8zuPaqh5TLcsHXp0/lQUiOV2uVHnAt503A +HY1v4PhlZ3G0CRZMenafU0Ky7a6zhrqFvWgtSdo+vN0S9xS/KJuTaWsYgOAt4r2I +K1uwuWuvA5L1Qrdj8pDzMLkdlyHU1Jgjzk0rNQDTbUkZX9CAi/xKUGZysjWfOn1F +HC1vJ1sbP9nTXpWRain1/6yatB2RxLTvWYyAq9IsL/8PAiEAkY8lGryvcZI/pxXt +XwSaXEL2d77GSGICMGZa1wOJtdEDgYQAAoGALAUljkOi1PxjjFVvhGfK95yIsrfb +fcIEKUBaTs9NR2rbGWUeP+93paoXwP39X9wrJx2MSWeHWhWKszNgoiyqYT0k4R9m +em3WClotxOvB5fHfwIp2kQYvE7H0/TPdGhfUpHQGYpyLQgT6L80meSKMFnu4VXGz +OANhWDxu3JxiADCjgZQwgZEwCwYDVR0PBAQDAgMIMEIGCWCGSAGG+EIBDQQ1FjNU +aGlzIGNlcnRpZmljYXRlIGNhbm5vdCBiZSB0cnVzdGVkIGZvciBhbnkgcHVycG9z +ZS4wHQYDVR0OBBYEFO37wHcauyc03rDc6cDRRsHzgcK+MB8GA1UdIwQYMBaAFM1I +ZQGDsqYHWwb+I4EMxHPk0bU4MAsGCWCGSAFlAwQDAgNHADBEAiB1LU0esRdHDvSj +kqAm+3viU2a+hl66sLrK5lYBOYqGYAIgWG7bDxqFVP6/stHfdbeMovLejquEl9tr +iPEBA+EDHjk= +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.dh_cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + spki_a = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + + self.assertEqual(rfc3279.dhpublicnumber, spki_a['algorithm']) + + spki_a_p, rest = der_decoder( + spki_a['parameters'], asn1Spec=rfc3279.DomainParameters()) + + self.assertFalse(rest) + self.assertTrue(spki_a_p.prettyPrint()) + self.assertEqual(spki_a['parameters'], der_encoder(spki_a_p)) + + q_value = 65838278260281264030127352144753816831178774189428428256716126077244217603537 + + self.assertEqual(q_value, spki_a_p['q']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.dh_cert_pem_text) + asn1Object, rest = der_decoder(substrate, + asn1Spec=self.asn1Spec, + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + spki_a = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + + self.assertEqual(rfc3279.dhpublicnumber, spki_a['algorithm']) + + q_value = 65838278260281264030127352144753816831178774189428428256716126077244217603537 + + self.assertEqual(q_value, spki_a['parameters']['q']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc3280.py b/tests/test_rfc3280.py new file mode 100644 index 0000000..3031335 --- /dev/null +++ b/tests/test_rfc3280.py @@ -0,0 +1,79 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc3280 + + +class CertificateTestCase(unittest.TestCase): + pem_text = """\ +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy +NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD +cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs +2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY +JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE +Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ +n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A +PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu +""" + + def setUp(self): + self.asn1Spec = rfc3280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + +class CertificateListTestCase(unittest.TestCase): + pem_text = """\ +MIIBVjCBwAIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJBVTETMBEGA1UE +CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk +MRUwEwYDVQQDEwxzbm1wbGFicy5jb20xIDAeBgkqhkiG9w0BCQEWEWluZm9Ac25t +cGxhYnMuY29tFw0xMjA0MTExMzQwNTlaFw0xMjA1MTExMzQwNTlaoA4wDDAKBgNV +HRQEAwIBATANBgkqhkiG9w0BAQUFAAOBgQC1D/wwnrcY/uFBHGc6SyoYss2kn+nY +RTwzXmmldbNTCQ03x5vkWGGIaRJdN8QeCzbEi7gpgxgpxAx6Y5WkxkMQ1UPjNM5n +DGVDOtR0dskFrrbHuNpWqWrDaBN0/ryZiWKjr9JRbrpkHgVY29I1gLooQ6IHuKHY +vjnIhxTFoCb5vA== +""" + + def setUp(self): + self.asn1Spec = rfc3280.CertificateList() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc3281.py b/tests/test_rfc3281.py new file mode 100644 index 0000000..f03316f --- /dev/null +++ b/tests/test_rfc3281.py @@ -0,0 +1,80 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc3281 + + +class AttributeCertificateTestCase(unittest.TestCase): + pem_text = """\ +MIIDBTCCAm4CAQEwgY+gUTBKpEgwRjEjMCEGA1UEAwwaQUNNRSBJbnRlcm1lZGlh +dGUgRUNEU0EgQ0ExCzAJBgNVBAYTAkZJMRIwEAYDVQQKDAlBQ01FIEx0ZC4CAx7N +WqE6pDgwNjETMBEGA1UEAwwKQUNNRSBFQ0RTQTELMAkGA1UEBhMCRkkxEjAQBgNV +BAoMCUFDTUUgTHRkLqA9MDukOTA3MRQwEgYDVQQDDAtleGFtcGxlLmNvbTELMAkG +A1UEBhMCRkkxEjAQBgNVBAoMCUFDTUUgTHRkLjANBgkqhkiG9w0BAQsFAAIEC63K +/jAiGA8yMDE2MDEwMTEyMDAwMFoYDzIwMTYwMzAxMTIwMDAwWjCB8jA8BggrBgEF +BQcKATEwMC6GC3VybjpzZXJ2aWNlpBUwEzERMA8GA1UEAwwIdXNlcm5hbWUECHBh +c3N3b3JkMDIGCCsGAQUFBwoCMSYwJIYLdXJuOnNlcnZpY2WkFTATMREwDwYDVQQD +DAh1c2VybmFtZTA1BggrBgEFBQcKAzEpMCegGKQWMBQxEjAQBgNVBAMMCUFDTUUg +THRkLjALDAlBQ01FIEx0ZC4wIAYIKwYBBQUHCgQxFDASMBAMBmdyb3VwMQwGZ3Jv +dXAyMCUGA1UESDEeMA2hC4YJdXJuOnJvbGUxMA2hC4YJdXJuOnJvbGUyMGowHwYD +VR0jBBgwFoAUgJCMhskAsEBzvklAX8yJBOXO500wCQYDVR04BAIFADA8BgNVHTcB +Af8EMjAwMB2gCoYIdXJuOnRlc3SgD4INKi5leGFtcGxlLmNvbTAPoA2GC3Vybjph +bm90aGVyMA0GCSqGSIb3DQEBCwUAA4GBACygfTs6TkPurZQTLufcE3B1H2707OXK +sJlwRpuodR2oJbunSHZ94jcJHs5dfbzFs6vNfVLlBiDBRieX4p+4JcQ2P44bkgyi +UTJu7g1b6C1liB3vO6yH5hOZicOAaKd+c/myuGb9uJ4n6y2oLNxnk/fDzpuZUe2h +Q4eikPk4LQey +""" + + def setUp(self): + self.asn1Spec = rfc3281.AttributeCertificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(1, asn1Object['acinfo']['version']) + + attributeMap = { + rfc3281.id_at_role: rfc3281.RoleSyntax(), + rfc3281.id_aca_authenticationInfo: rfc3281.SvceAuthInfo(), + rfc3281.id_aca_accessIdentity: rfc3281.SvceAuthInfo(), + rfc3281.id_aca_chargingIdentity: rfc3281.IetfAttrSyntax(), + rfc3281.id_aca_group: rfc3281.IetfAttrSyntax(), + } + + count = 0 + + for attr in asn1Object['acinfo']['attributes']: + self.assertIn(attr['type'], attributeMap) + + av, rest = der_decoder( + attr['values'][0], asn1Spec=attributeMap[attr['type']]) + + self.assertFalse(rest) + self.assertTrue(av.prettyPrint()) + self.assertEqual(attr['values'][0], der_encoder(av)) + + count += 1 + + self.assertEqual(5, count) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc3370.py b/tests/test_rfc3370.py new file mode 100644 index 0000000..70d9d42 --- /dev/null +++ b/tests/test_rfc3370.py @@ -0,0 +1,234 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc3370 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5751 + + +class EnvelopedDataTestCase(unittest.TestCase): + env_data_pem_text = """\ +MIIFjAYJKoZIhvcNAQcDoIIFfTCCBXkCAQIxZqJkAgEEMCMEEH744tkBAA6gplAQ +nKYxCF8YDzIwMTkwOTEyMTIwMDAwWjAQBgsqhkiG9w0BCRADBwIBOgQocOaZ+1cB +94MzMPtx6HyFpCC9yZrwXSKvWg5I018xOJhsuq+0so1PNTCCBQoGCSqGSIb3DQEH +ATAZBggqhkiG9w0DAjANAgE6BAhCT0dVU19JVoCCBOBzx7F6GMkP+C0Q4iuDq0rk +SZprg8nuXx/4S3IMP999BrJdUAbPYxdQhAwTOZIuueyv00TJe/Eam9yyLuZXy0PF +lTRi7KED8L8cyHsRoEobWGMLvE3D4hEhTGttElqQxBvMxZZgm6kLnNG7j8Z72L4l +U4aARLYTQvktlJnnfCaccDSiWzU8eXcXdnZAzcKR7CoDc0/XBpdDRddvQ7KXoarX +YHuSybt649YDcpy0SN9gEPqcFPrBB3nusAx4VOTlpx5Z3ZJv/TEymN8KDobNfykB +ZURTwupO9WaVJZ3Hd/d8C1SCJn6DHuM1jwDp26WfzO8xCfea08MJrnQbNKsDHwmt +4dFZIOvcOnwR8nNSB/Lt1aUj3GzluHVMyQQyT4AdZDmwFdNmQOBUBLmbWYhtd7t3 +O7Eqx8bGNa7V7LL0nvua04aj1oA6ph/G/8jxhByBYdN5Bwg7f1Ga3ZCwju2tFoQn +WOCPYTVOjmBEJshBbNC7KhLpp9+C7/13A9cIC3T7Reuc7m+Fopf9Fabu97yFiyJP +S8jSF0EnesNGR1L1Uvo2Wdc66iECoSrxvezaSgGKB2uLTnaFx4ASVMcP7gDipEOI +wuUUuVCqgmWkHAK0Q9mwhBLLrYrsn9OjDHFpvkWgWNRMLl/v3E9A+grFh2BQHkB4 +C7keB1ZOfj1SqDi/+ylM9I1FOYMxVXJn2qHMl+QOkfdMoIATm3n3DiBI97/uX4x5 +KaX074v0dN31WeDcsFsh2ze5Dhx8vLJCaXLzWqkmNHX5G/CjjqE6bSR/awgWLRZQ +uY/9fMvDpvVJuId/+OoWDtMVPIsyQ8w8yZzv+SkuZhsrJMHiKd5qxNQv5sOvC765 +LMUCNNwj7WzPhajintFXLAEMpIjk5xt3eIy3hdYla3PQoFfqcHOVX4EFMLBoYwBT +gik8Fg669yXtMlbH84MGNs7jObhP/rrDkgbe0qmxUyzgm2uHya1VcItMGYoPPKMF +U3ZfwAsZdqsi1GAtruTzSUmOpMfAoKOIAyZP96HrsrPCaoGrn7ysm5eRrHQ2hdwO +7rGQIw0dRAFh2eyRomoLam7yEiw9M6uHuJ5hIS5yEW+7uUjQT6nvKlbrkIyLL5j9 +Gbk5Z4fOMqRTkBs+3H8x7a+lBEKBo/ByJm6fHYi+LX5ZhQFTWkY0M7tfPtrxQdsN +RGSHtv7jS7PZ3thCMqCtkG/pjAsCbDUtMThtP08z2fstE6dfy7qSx6LzKLDyBl5W +76mVYdsX7Q72yIoCDFmUGdrRcWA+l3OMwNNL+x9MhhdaUWPtxqaGyZMNGOjkbYHb +XZ69oqYqCHkAstIVKTzpk3kq9C9x+ynzWO8kIGYNK2uxSBIzPLQ6Daq4c53rWFFN +WVjPC8m98zMcYp0hbBhRsdk4qj8osSTcTfpT0+Q+hkYQvZl4IfgX1aHeaCDSScF8 +SaU+cZ7GYFvLo1cYrtVbeXrFwmWl0xpco1Ux+XZgryT/fgfJ+3ToppgsQmzECqTW +mYsSYaF1kLU4Cqi9UH/VqBLOkwxoH05Zao2xOMNzu2QO3wFnvY2wBsIj1eaxfzVb +42o9vom7V20jT1ufXXctf9ls5J1WJxBxdKmXQWdNloeAcl1AtxTbw7vIUU5uWqu9 +wwqly11MDVPAb0tcQW20auWmCNkXd52jQJ7PXR6kr5I= +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.env_data_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_envelopedData, asn1Object['contentType']) + + ed, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.EnvelopedData()) + self.assertFalse(rest) + self.assertTrue(ed.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(ed)) + + kwa = ed['recipientInfos'][0]['kekri']['keyEncryptionAlgorithm'] + self.assertEqual(rfc3370.id_alg_CMSRC2wrap, kwa['algorithm']) + kwa_param, rest = der_decoder( + kwa['parameters'], rfc3370.RC2wrapParameter()) + self.assertFalse(rest) + self.assertTrue(kwa_param.prettyPrint()) + self.assertEqual(kwa['parameters'], der_encoder(kwa_param)) + self.assertEqual(58, kwa_param) + + cea = ed['encryptedContentInfo']['contentEncryptionAlgorithm'] + self.assertEqual(rfc3370.rc2CBC, cea['algorithm']) + param, rest = der_decoder( + cea['parameters'], rfc3370.RC2CBCParameter()) + self.assertFalse(rest) + self.assertTrue(param.prettyPrint()) + self.assertEqual(cea['parameters'], der_encoder(param)) + + iv = univ.OctetString(hexValue='424f4755535f4956') + self.assertEqual(iv, param['iv']) + self.assertEqual(58, param['rc2ParameterVersion']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.env_data_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertTrue(asn1Object['contentType'] in rfc5652.cmsContentTypesMap.keys()) + + ri0 = asn1Object['content']['recipientInfos'][0] + kwa = ri0['kekri']['keyEncryptionAlgorithm'] + self.assertEqual(rfc3370.id_alg_CMSRC2wrap, kwa['algorithm']) + self.assertEqual(58, kwa['parameters']) + + eci = asn1Object['content']['encryptedContentInfo'] + cea = eci['contentEncryptionAlgorithm'] + self.assertEqual(rfc3370.rc2CBC, cea['algorithm']) + + iv = univ.OctetString(hexValue='424f4755535f4956') + self.assertEqual(iv, cea['parameters']['iv']) + self.assertEqual(58, cea['parameters']['rc2ParameterVersion']) + +class DSAPublicKeyTestCase(unittest.TestCase): + dsa_cert_pem_text = """\ +MIIDpjCCA0ygAwIBAgIUY8xt3l0B9nIPWSpjs0hDJUJZmCkwCwYJYIZIAWUDBAMC +MD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJWQTEQMA4GA1UEBxMHSGVybmRvbjER +MA8GA1UEChMIQm9ndXMgQ0EwHhcNMTkxMDIwMjAxMjMwWhcNMjAxMDE5MjAxMjMw +WjBwMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24x +EDAOBgNVBAoTB0V4YW1wbGUxDjAMBgNVBAsTBUFsaWNlMSAwHgYJKoZIhvcNAQkB +FhFhbGljZUBleGFtcGxlLmNvbTCCAbYwggErBgcqhkjOOAQBMIIBHgKBgQCLpR53 +xHfe+SiknAK/L9lm/ZO1109c9iYkriPIW/5MMlM+qc/tdRkKpG6ELIpfXTPtKCJm +zqqVIyTmAJryyE8Xw0Ie2mzYPU5ULvKmllQkjTsWgPGgQBkciZ0AW9ggD9VwZilg +4qh3iSO7T97hVQFnpCh6vm8pOH6UP/5kpr9ZJQIVANzdbztBJlJfqCB1t4h/NvSu +wCFvAoGAITP+jhYk9Rngd98l+5ccgauQ+cLEUBgNG2Wq56zBXQbLou6eKkQi7ecL +NiRmExq3IU3LOj426wSxL72Kw6FPyOEv3edIFkJJEHL4Z+ZJeVe//dzya0ddOJ7k +k6qNF2ic+viD/5Vm8yRyKiig2uHH/MgIesLdZnvbzvX+f/P0z50DgYQAAoGALAUl +jkOi1PxjjFVvhGfK95yIsrfbfcIEKUBaTs9NR2rbGWUeP+93paoXwP39X9wrJx2M +SWeHWhWKszNgoiyqYT0k4R9mem3WClotxOvB5fHfwIp2kQYvE7H0/TPdGhfUpHQG +YpyLQgT6L80meSKMFnu4VXGzOANhWDxu3JxiADCjgZQwgZEwCwYDVR0PBAQDAgeA +MEIGCWCGSAGG+EIBDQQ1FjNUaGlzIGNlcnRpZmljYXRlIGNhbm5vdCBiZSB0cnVz +dGVkIGZvciBhbnkgcHVycG9zZS4wHQYDVR0OBBYEFO37wHcauyc03rDc6cDRRsHz +gcK+MB8GA1UdIwQYMBaAFM1IZQGDsqYHWwb+I4EMxHPk0bU4MAsGCWCGSAFlAwQD +AgNHADBEAiBBRbfMzLi7+SVyO8SM3xxwUsMf/k1B+Nkvf1kBTfCfGwIgSAx/6mI+ +pNqdXqZZGESXy1MT1aBc4ynPGLFUr2r7cPY= +""" + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.dsa_cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + spki = asn1Object['tbsCertificate']['subjectPublicKeyInfo'] + self.assertEqual(rfc3370.id_dsa, spki['algorithm']['algorithm']) + pk_substrate = spki['subjectPublicKey'].asOctets() + + pk, rest = der_decoder(pk_substrate, asn1Spec=rfc3370.Dss_Pub_Key()) + self.assertFalse(rest) + self.assertTrue(pk.prettyPrint()) + self.assertEqual(pk_substrate, der_encoder(pk)) + + self.assertEqual(48, pk % 1024) + +class SMIMECapabilitiesTestCase(unittest.TestCase): + smime_capabilities_pem_text = """\ +MGIwDAYIKwYBBQUIAQIFADAfBgsqhkiG9w0BCRADBTAQBgsqhkiG9w0BCRADBwIB +OjAfBgsqhkiG9w0BCRADCjAQBgsqhkiG9w0BCRADBwIBOjAQBgsqhkiG9w0BCRAD +BwIBOg== +""" + + def setUp(self): + self.asn1Spec = rfc5751.SMIMECapabilities() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.smime_capabilities_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + found_wrap_alg_param = False + for cap in asn1Object: + if cap['capabilityID'] in rfc5751.smimeCapabilityMap.keys(): + if cap['parameters'].hasValue(): + param, rest = der_decoder( + cap['parameters'], + asn1Spec=rfc5751.smimeCapabilityMap[cap['capabilityID']]) + self.assertFalse(rest) + self.assertTrue(param.prettyPrint()) + self.assertEqual(cap['parameters'], der_encoder(param)) + + if cap['capabilityID'] == rfc3370.id_alg_ESDH: + kwa, rest = der_decoder( + cap['parameters'], + asn1Spec=rfc5751.smimeCapabilityMap[cap['capabilityID']]) + self.assertFalse(rest) + self.assertTrue(kwa.prettyPrint()) + self.assertEqual(cap['parameters'], der_encoder(kwa)) + + self.assertTrue(kwa['algorithm'] in rfc5280.algorithmIdentifierMap.keys()) + self.assertEqual(rfc3370.id_alg_CMSRC2wrap, kwa['algorithm']) + kwa_p, rest = der_decoder( + kwa['parameters'], + asn1Spec=rfc5280.algorithmIdentifierMap[kwa['algorithm']]) + self.assertFalse(rest) + self.assertTrue(kwa_p.prettyPrint()) + self.assertEqual(kwa['parameters'], der_encoder(kwa_p)) + self.assertEqual(58, kwa_p) + found_wrap_alg_param = True + + self.assertTrue(found_wrap_alg_param) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.smime_capabilities_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + found_wrap_alg_param = False + for cap in asn1Object: + if cap['capabilityID'] == rfc3370.id_alg_ESDH: + self.assertEqual(rfc3370.id_alg_CMSRC2wrap, cap['parameters']['algorithm']) + self.assertEqual(58, cap['parameters']['parameters']) + found_wrap_alg_param = True + + self.assertTrue(found_wrap_alg_param) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) + diff --git a/tests/test_rfc3447.py b/tests/test_rfc3447.py new file mode 100644 index 0000000..8788691 --- /dev/null +++ b/tests/test_rfc3447.py @@ -0,0 +1,66 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc3447 + + +# openssl genrsa -primes 3 -f4 -out multiprime.key + +class MultiprimeRSAPrivateKeyTestCase(unittest.TestCase): + pem_text = """\ +MIIE2QIBAQKCAQEAn82EqwXasE2TFNSmZucB8LNza2mOWLHF3nxpxKXalPMDvezc +5Dq7Ytcv/k9jJL4j4jYfvR4yyZdU9iHLaD6hOINZ8E6hVpx/4c96ZUSOLzD2g+u+ +jIuoNfG+zygSBGYCS6BLCAIsZ+2wUyxYpLJknHJld9/jy+aLmmyrilhH9dH5AUiV +3NeWht/68++dMXf4ZI/gV4bMSlWhggxkz2WJJpiQdCdJatGkwNDkHmLA9X0tC6OH +SPE7qYdxG38cYS5F445SgnhDpiK7BodSqYLwgehaDjoOYdEgHVnOcpBCDI5zCJSL +b1c/z8uhrB1xxlECR44wCLcKsIIYQxaEErRJ/wIDAQABAoIBAD+Ra5L0szeqxDVn +GgKZJkZvvBwgU0WpAgMtDo3xQ/A4c2ab0IrhaiU5YJgTUGcPVArqaNm8J4vVrTBz +5QxEzbFDXwWe4cMoYh6bgB7ElKLlIUr8/kGZUfgc7kI29luEjcAIEAC2/RQHesVn +DHkL5OzqZL+4fIwckAMh0tXdflsPgZ/jgIaKca4OqKu4KGnczm3UvqtlvwisAjkx +zMyfZXOLn0vEwP2bfbhQrCVrP7n6a+CV+Kqm8NBWnbiS6x2rWemVVssNTbfXQztq +wC6ZJZCLK7plciDBWvHcS6vxdcsS9DUxuqSV6o/stCGTl1D+9tDx8Od0Eunna2B2 +wAoRHZECVgbNO1bqwfYpp5aFuySWoP+KZz8f/5ZkHjLwiNGpQcqVd4+7Ql2R4qgF +NgSoQQOZFhKtiOeLVU0HYfp6doI4waSINZdF/fJDHD6fY3AMOc/IIMDHHIzbAlYG +vKOocLXWj/2+gcyQ1XoAmrE70aIFUBLSvd7RCi8GI74zYWp5lCSvO850Z4GsWSZT +41iF13sTDDJPm3+BbzMvEu2GuACi/8/IpbUr24/FP9Cp1Rf7kwJWAgMxfoshbrNu +ebQB5laHNnT+DYhrOFVRNiNDaD2bUNSetrFidosWtD4ueHxMGENwa4BbFJ9+UrdP +fyxC6k7exM7khGjaNZczwTep1VpYtKjzP/bp9KcCVgYoj9s9HZ1FCAsNEPodjGfd +AcPTQS9mIa7wzy19B7uvFQJXPURi/p4KKBMVQ99Pp8/r9lJzxxiEf8FyPr8N7lZM +EUKkFkDrZQDhKpsrHWSNj6yRFlltAlYC7dYR8KLEWoOUATLosxQhwgypv+23r+d4 +ZdPOdDv9n8Kmj+NFy/oISFfdXzlOU4RWQtMx3hEwAabwct7vjiJEej/kmiTqco02 +17tt13VvvQ5ZXF73dDCCAQwwggEIAlYDfMpM1WNfxcLLOgkRZ+0S9OvIrEOi0ALV +SquTdi/thhCuCsK3lMD4miN9te8j16YtqEFVWXC3a6DWwIJ6m/xZ50bBwPqM8RsI +6FWhZw4Dr5VqjYXUvwJWAvapRk9SydDYri/cAtGIkUJVlspkE1emALAaSw30vmfd +hrgYLT6YGOmK3UmcNJ4NVeET275MXWF1ZOhkOGKTN6aj5wPhJaHBMnmUQrq7GwC6 +/LfUkSsCVgMCDTV9gbFW8u6TcTVW85dBIeUGxZh1T2pbU3dkGO3IOxOhzJUplH4/ +EeEs9dusHakg1ERXAg4Vo1YowPW8kuVbZ9faxeVrmuER5NcCuZzS5X/obGUw +""" + + def setUp(self): + self.asn1Spec = rfc3447.RSAPrivateKey() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc3537.py b/tests/test_rfc3537.py new file mode 100644 index 0000000..1b7490b --- /dev/null +++ b/tests/test_rfc3537.py @@ -0,0 +1,76 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc3537 +from pyasn1_modules import rfc5751 + + +class SMIMECapabilitiesTestCase(unittest.TestCase): + smime_capabilities_pem_text = "MCIwDwYLKoZIhvcNAQkQAwwFADAPBgsqhkiG9w0BCRADCwUA" + + def setUp(self): + self.asn1Spec = rfc5751.SMIMECapabilities() + + def testDerCodec(self): + alg_oid_list = [ + rfc3537.id_alg_HMACwithAESwrap, + rfc3537.id_alg_HMACwith3DESwrap, + ] + + substrate = pem.readBase64fromText(self.smime_capabilities_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + count = 0 + for cap in asn1Object: + self.assertEqual(der_encoder(univ.Null("")), cap['parameters']) + self.assertTrue(cap['capabilityID'] in alg_oid_list) + count += 1 + + self.assertEqual(count, 2) + + def testOpenTypes(self): + openTypesMap = { + rfc3537.id_alg_HMACwithAESwrap: univ.Null(""), + rfc3537.id_alg_HMACwith3DESwrap: univ.Null(""), + } + + asn1Spec=rfc5751.SMIMECapabilities() + substrate = pem.readBase64fromText(self.smime_capabilities_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, + openTypes=openTypesMap, decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + count = 0 + for cap in asn1Object: + self.assertEqual(univ.Null(""), cap['parameters']) + self.assertTrue(cap['capabilityID'] in openTypesMap.keys()) + count += 1 + + self.assertEqual(count, 2) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc3560.py b/tests/test_rfc3560.py new file mode 100644 index 0000000..3419cde --- /dev/null +++ b/tests/test_rfc3560.py @@ -0,0 +1,68 @@ +# +# 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 +import unittest + +from pyasn1.codec.der import decoder as der_decoder +from pyasn1.codec.der import encoder as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc3560 + + +class OAEPDefautTestCase(unittest.TestCase): + oaep_default_pem_text = "MAsGCSqGSIb3DQEBBw==" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.oaep_default_pem_text) + asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(rfc3560.id_RSAES_OAEP, asn1Object[0]) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + +class OAEPSHA256TestCase(unittest.TestCase): + oaep_sha256_pem_text = "MDwGCSqGSIb3DQEBBzAvoA8wDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIBBQA=" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.oaep_sha256_pem_text) + asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(rfc3560.id_RSAES_OAEP, asn1Object[0]) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + +class OAEPFullTestCase(unittest.TestCase): + oaep_full_pem_text = "MFMGCSqGSIb3DQEBBzBGoA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiFTATBgkqhkiG9w0BAQkEBmZvb2Jhcg==" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.oaep_full_pem_text) + asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(rfc3560.id_RSAES_OAEP, asn1Object[0]) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc3565.py b/tests/test_rfc3565.py new file mode 100644 index 0000000..58574ec --- /dev/null +++ b/tests/test_rfc3565.py @@ -0,0 +1,68 @@ +# +# 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 +import unittest + +from pyasn1.codec.der import decoder as der_decoder +from pyasn1.codec.der import encoder as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc3565 + + +class AESKeyWrapTestCase(unittest.TestCase): + kw_alg_id_pem_text = "MAsGCWCGSAFlAwQBLQ==" + + def setUp(self): + self.asn1Spec = rfc3565.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.kw_alg_id_pem_text) + asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(rfc3565.id_aes256_wrap, asn1Object[0]) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + +class AESCBCTestCase(unittest.TestCase): + aes_alg_id_pem_text = "MB0GCWCGSAFlAwQBKgQQEImWuoUOPwM5mTu1h4oONw==" + + def setUp(self): + self.asn1Spec = rfc3565.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.aes_alg_id_pem_text) + asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(rfc3565.id_aes256_CBC, asn1Object[0]) + self.assertTrue(asn1Object[1].isValue) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.aes_alg_id_pem_text) + asn1Object, rest = der_decoder.decode(substrate, + asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(rfc3565.id_aes256_CBC, asn1Object[0]) + + aes_iv = univ.OctetString(hexValue='108996ba850e3f0339993bb5878a0e37') + + self.assertEqual(aes_iv, asn1Object[1]) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc3657.py b/tests/test_rfc3657.py new file mode 100644 index 0000000..12b49dc --- /dev/null +++ b/tests/test_rfc3657.py @@ -0,0 +1,167 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc3657 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5751 + + +class EnvelopedDataTestCase(unittest.TestCase): + env_data_pem_text = """\ +MIIFfwYJKoZIhvcNAQcDoIIFcDCCBWwCAQIxU6JRAgEEMCMEECBlcTFnxBsPlsug +4KOCj78YDzIwMTkwOTEyMTIwMDAwWjANBgsqgwiMmks9AQEDAgQYS3mK9jQmvth1 +iuBV8PEa89ICvmoomJCvMIIFEAYJKoZIhvcNAQcBMB8GCyqDCIyaSz0BAQECBBBC +T0dVU0lWX0JPR1VTSVYhgIIE4HPHsXoYyQ/4LRDiK4OrSuRJmmuDye5fH/hLcgw/ +330Gsl1QBs9jF1CEDBM5ki657K/TRMl78Rqb3LIu5lfLQ8WVNGLsoQPwvxzIexGg +ShtYYwu8TcPiESFMa20SWpDEG8zFlmCbqQuc0buPxnvYviVThoBEthNC+S2Umed8 +JpxwNKJbNTx5dxd2dkDNwpHsKgNzT9cGl0NF129Dspehqtdge5LJu3rj1gNynLRI +32AQ+pwU+sEHee6wDHhU5OWnHlndkm/9MTKY3woOhs1/KQFlRFPC6k71ZpUlncd3 +93wLVIImfoMe4zWPAOnbpZ/M7zEJ95rTwwmudBs0qwMfCa3h0Vkg69w6fBHyc1IH +8u3VpSPcbOW4dUzJBDJPgB1kObAV02ZA4FQEuZtZiG13u3c7sSrHxsY1rtXssvSe ++5rThqPWgDqmH8b/yPGEHIFh03kHCDt/UZrdkLCO7a0WhCdY4I9hNU6OYEQmyEFs +0LsqEumn34Lv/XcD1wgLdPtF65zub4Wil/0Vpu73vIWLIk9LyNIXQSd6w0ZHUvVS ++jZZ1zrqIQKhKvG97NpKAYoHa4tOdoXHgBJUxw/uAOKkQ4jC5RS5UKqCZaQcArRD +2bCEEsutiuyf06MMcWm+RaBY1EwuX+/cT0D6CsWHYFAeQHgLuR4HVk5+PVKoOL/7 +KUz0jUU5gzFVcmfaocyX5A6R90yggBObefcOIEj3v+5fjHkppfTvi/R03fVZ4Nyw +WyHbN7kOHHy8skJpcvNaqSY0dfkb8KOOoTptJH9rCBYtFlC5j/18y8Om9Um4h3/4 +6hYO0xU8izJDzDzJnO/5KS5mGyskweIp3mrE1C/mw68LvrksxQI03CPtbM+FqOKe +0VcsAQykiOTnG3d4jLeF1iVrc9CgV+pwc5VfgQUwsGhjAFOCKTwWDrr3Je0yVsfz +gwY2zuM5uE/+usOSBt7SqbFTLOCba4fJrVVwi0wZig88owVTdl/ACxl2qyLUYC2u +5PNJSY6kx8Cgo4gDJk/3oeuys8JqgaufvKybl5GsdDaF3A7usZAjDR1EAWHZ7JGi +agtqbvISLD0zq4e4nmEhLnIRb7u5SNBPqe8qVuuQjIsvmP0ZuTlnh84ypFOQGz7c +fzHtr6UEQoGj8HImbp8diL4tflmFAVNaRjQzu18+2vFB2w1EZIe2/uNLs9ne2EIy +oK2Qb+mMCwJsNS0xOG0/TzPZ+y0Tp1/LupLHovMosPIGXlbvqZVh2xftDvbIigIM +WZQZ2tFxYD6Xc4zA00v7H0yGF1pRY+3GpobJkw0Y6ORtgdtdnr2ipioIeQCy0hUp +POmTeSr0L3H7KfNY7yQgZg0ra7FIEjM8tDoNqrhznetYUU1ZWM8Lyb3zMxxinSFs +GFGx2TiqPyixJNxN+lPT5D6GRhC9mXgh+BfVod5oINJJwXxJpT5xnsZgW8ujVxiu +1Vt5esXCZaXTGlyjVTH5dmCvJP9+B8n7dOimmCxCbMQKpNaZixJhoXWQtTgKqL1Q +f9WoEs6TDGgfTllqjbE4w3O7ZA7fAWe9jbAGwiPV5rF/NVvjaj2+ibtXbSNPW59d +dy1/2WzknVYnEHF0qZdBZ02Wh4ByXUC3FNvDu8hRTm5aq73DCqXLXUwNU8BvS1xB +bbRq5aYI2Rd3naNAns9dHqSvkg== +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.env_data_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_envelopedData, asn1Object['contentType']) + + ed, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.EnvelopedData()) + + self.assertFalse(rest) + self.assertTrue(ed.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(ed)) + + kwa = ed['recipientInfos'][0]['kekri']['keyEncryptionAlgorithm'] + self.assertEqual(rfc3657.id_camellia128_wrap, kwa['algorithm']) + + cea = ed['encryptedContentInfo']['contentEncryptionAlgorithm'] + self.assertEqual(rfc3657.id_camellia128_cbc, cea['algorithm']) + param, rest = der_decoder( + cea['parameters'], asn1Spec=rfc3657.Camellia_IV()) + + self.assertFalse(rest) + self.assertTrue(param.prettyPrint()) + self.assertEqual(cea['parameters'], der_encoder(param)) + + iv = rfc3657.Camellia_IV(hexValue='424f47555349565f424f475553495621') + self.assertEqual(iv, param) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.env_data_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertTrue(asn1Object['contentType'] in rfc5652.cmsContentTypesMap.keys()) + + kekri = asn1Object['content']['recipientInfos'][0]['kekri'] + kwa = kekri['keyEncryptionAlgorithm'] + self.assertEqual(rfc3657.id_camellia128_wrap, kwa['algorithm']) + + eci = asn1Object['content']['encryptedContentInfo'] + cea = eci['contentEncryptionAlgorithm'] + self.assertEqual(rfc3657.id_camellia128_cbc, cea['algorithm']) + + iv = rfc3657.Camellia_IV(hexValue='424f47555349565f424f475553495621') + self.assertEqual(iv, cea['parameters']) + +class SMIMECapabilitiesTestCase(unittest.TestCase): + smime_capabilities_pem_text = """\ +MGYwDwYLKoMIjJpLPQEBAQIFADAPBgsqgwiMmks9AQEBAwUAMA8GCyqDCIyaSz0B +AQEEBQAwDwYLKoMIjJpLPQEBAwIFADAPBgsqgwiMmks9AQEDAwUAMA8GCyqDCIya +Sz0BAQMEBQA= +""" + + def setUp(self): + self.asn1Spec = rfc5751.SMIMECapabilities() + + def testDerCodec(self): + alg_oid_list = [ + rfc3657.id_camellia128_cbc, + rfc3657.id_camellia192_cbc, + rfc3657.id_camellia256_cbc, + rfc3657.id_camellia128_wrap, + rfc3657.id_camellia192_wrap, + rfc3657.id_camellia256_wrap, + ] + + substrate = pem.readBase64fromText(self.smime_capabilities_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + param = der_encoder(rfc3657.CamelliaSMimeCapability("")) + count = 0 + for cap in asn1Object: + self.assertEqual(cap['parameters'], param) + self.assertTrue(cap['capabilityID'] in alg_oid_list) + count += 1 + + self.assertEqual(count, 6) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.smime_capabilities_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + param = rfc3657.CamelliaSMimeCapability("") + count = 0 + for cap in asn1Object: + self.assertTrue(cap['capabilityID'] in rfc5751.smimeCapabilityMap.keys()) + self.assertEqual(cap['parameters'], param) + count += 1 + + self.assertEqual(count, 6) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc3709.py b/tests/test_rfc3709.py new file mode 100644 index 0000000..dcab4b6 --- /dev/null +++ b/tests/test_rfc3709.py @@ -0,0 +1,194 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc3709 + + +class CertificateExtnWithUrlTestCase(unittest.TestCase): + pem_text = """\ +MIIC9zCCAn2gAwIBAgIJAKWzVCgbsG46MAoGCCqGSM49BAMDMD8xCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9n +dXMgQ0EwHhcNMTkwNTE0MTAwMjAwWhcNMjAwNTEzMTAwMjAwWjBlMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xGzAZBgNVBAoTElZp +Z2lsIFNlY3VyaXR5IExMQzEaMBgGA1UEAxMRbWFpbC52aWdpbHNlYy5jb20wdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAATwUXZUseiOaqWdrClDCMbp9YFAM87LTmFirygp +zKDU9cfqSCg7zBDIphXCwMcS9zVWDoStCbcvN0jw5CljHcffzpHYX91P88SZRJ1w +4hawHjOsWxvM3AkYgZ5nfdlL7EajggEdMIIBGTALBgNVHQ8EBAMCB4AwQgYJYIZI +AYb4QgENBDUWM1RoaXMgY2VydGlmaWNhdGUgY2Fubm90IGJlIHRydXN0ZWQgZm9y +IGFueSBwdXJwb3NlLjAdBgNVHQ4EFgQU8jXbNATapVXyvWkDmbBi7OIVCMEwHwYD +VR0jBBgwFoAU8jXbNATapVXyvWkDmbBi7OIVCMEwgYUGCCsGAQUFBwEMBHkwd6J1 +oHMwcTBvMG0WCWltYWdlL3BuZzAzMDEwDQYJYIZIAWUDBAIBBQAEIJtBNrMSSNo+ +6Rwqwctmcy0qf68ilRuKEmlf3GLwGiIkMCsWKWh0dHA6Ly93d3cudmlnaWxzZWMu +Y29tL3ZpZ2lsc2VjX2xvZ28ucG5nMAoGCCqGSM49BAMDA2gAMGUCMGhfLH4kZaCD +H43A8m8mHCUpYt9unT0qYu4TCMaRuOTYEuqj3qtuwyLcfAGuXKp/oAIxAIrPY+3y +Pj22pmfmQi5w21UljqoTj/+lQLkU3wfy5BdVKBwI0GfEA+YL3ctSzPNqAA== +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + extn_list = [] + + for extn in asn1Object['tbsCertificate']['extensions']: + extn_list.append(extn['extnID']) + + if extn['extnID'] == rfc3709.id_pe_logotype: + s = extn['extnValue'] + logotype, rest = der_decoder(s, rfc3709.LogotypeExtn()) + + self.assertFalse(rest) + self.assertTrue(logotype.prettyPrint()) + self.assertEqual(s, der_encoder(logotype)) + + ids = logotype['subjectLogo']['direct']['image'][0]['imageDetails'] + + self.assertEqual( "image/png", ids['mediaType']) + + expected = "http://www.vigilsec.com/vigilsec_logo.png" + self.assertEqual(expected, ids['logotypeURI'][0]) + + self.assertIn(rfc3709.id_pe_logotype, extn_list) + + def testExtensionsMap(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] in rfc5280.certificateExtensionsMap.keys(): + extnValue, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + +class CertificateExtnWithDataTestCase(unittest.TestCase): + pem_text = """\ +MIIJJDCCCAygAwIBAgIRAPIGo/5ScWbpAAAAAFwQBqkwDQYJKoZIhvcNAQELBQAw +gbkxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQL +Ex9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykg +MjAxOCBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxLTAr +BgNVBAMTJEVudHJ1c3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gVk1DMTAeFw0x +OTA4MzAxNDMyMzlaFw0yMDAyMjUxNTAyMzZaMIIBjTEOMAwGA1UEERMFMTAwMTcx +CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazERMA8GA1UEBxMITmV3IFlv +cmsxGDAWBgNVBAkTDzI3MCBQYXJrIEF2ZW51ZTETMBEGCysGAQQBgjc8AgEDEwJV +UzEZMBcGCysGAQQBgjc8AgECEwhEZWxhd2FyZTEfMB0GA1UEChMWSlBNb3JnYW4g +Q2hhc2UgYW5kIENvLjEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24xNzA1 +BgNVBAsTLkpQTUMgRmlyc3QgVmVyaWZpZWQgTWFyayBDZXJ0aWZpY2F0ZSBXb3Js +ZHdpZGUxDzANBgNVBAUTBjY5MTAxMTEXMBUGCisGAQQBg55fAQQTBzIwMTUzODkx +EjAQBgorBgEEAYOeXwEDEwJVUzEmMCQGCisGAQQBg55fAQITFmh0dHBzOi8vd3d3 +LnVzcHRvLmdvdi8xHzAdBgNVBAMTFkpQTW9yZ2FuIENoYXNlIGFuZCBDby4wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCNLY+etlX06q1MxA1VT/P20h1i +eFGTzX4fqSQNG+ypmjNfLa8YXraO1v1hahenkRUWrVPW0Hq3zKNJcCDmosox6+tB +59u0b1xgN8y8D05AEC7qoVVdbaWKENMxCN4CDfST6d3YOqApjqEFAGZ71s39tRRG +kmWGJb4jKXcUX8FWV8w/vjKrpipZ8JsX2tuOp2uxFLkmi+V7gvN8tpbHUipP5K7L +190VOBytSWPudXefnYG3UWRfwah7Fq1bKYT/cCwStUm8XlfA8nUumeVsAiyC6phs +adn26MYiSddsBU08TGthmunLAO0+shaBy6jHYZxMa37S67vVlDpxbeF+TPVXAgMB +AAGjggROMIIESjATBgorBgEEAdZ5AgQDAQH/BAIFADCCArAGCCsGAQUFBwEMBIIC +ojCCAp6iggKaoIICljCCApIwggKOMIICihYNaW1hZ2Uvc3ZnK3htbDAzMDEwDQYJ +YIZIAWUDBAIBBQAEIBnwW6ChGgWWIRn3qn/xGAOlhDflA3z5jhZcZTNDlxF5MIIC +QhaCAj5kYXRhOmltYWdlL3N2Zyt4bWw7YmFzZTY0LEg0c0lBQUFBQUFBQUFJV1Iz +V3JqTUJCR3I1dW5tR3F2Rml4NUpQODBObkZLRTVhbTRFSmhJYmVMazZpT1dhOXRa +TWQyOXVrN2NsTG9SV25CMHNENGNPYVR0TGdmLzVYUWE5TVdkWlV3S1pDQnJ2YjFv +YWp5aEoyNlZ6NW45OHZaNHBaemVOU1ZObGxYbXhnZUR2Vk93MU5abnRwdWFvRlNB +b1YwNFBmMkVYNk5UVzA2ZUNsUE9YK3FRRXpON1dWR0RLRkFoTldwS0ErQVB3RTRK +MzNiNXg5REtBYTdyTlV2cG40dFNwMndycWpPRElwRHd0THNyTTBmeVlCaVYyM0Nq +bDNYeEs0N0RJTVlQRkdiM0ZXSTZKTHZpc1JqV1ZSL1B3TmxGRVh1OUpmTmJtQk1H +RFlqZy9PMTlvVWVWclh0QWtJWTBEY0o0N2JKOXBTb01iclZwdGVNd3VmTDJjMml5 +Ym9qVU5veVlUOFFnL1VxWWtCNW41VW5QQWZYU2pub0tPbEl1eW5oOVRJVTh1Z3JF +YVMrVC9lRzZRWDh6OXl2YkdIZ0VLZjJ5S1h3dU9Sa2VsOGJQeFJoUHhtSnN0TDBT +bi9qOUtXWU8yR3dsM2EremNhbmhOYTV0YzZORkdHcVVFUUVwVmY0R3lVNnhOMnRx +WGgwWXQrM1BpcEhlK2l0cElRMGg0VHBoWnRrQ3plM0d6M2NjdllHbkp0cjZKVUNB +QUE9MCIGA1UdEQQbMBmCF2V4Y2hhZGRldi5sYWJtb3JnYW4uY29tMBMGA1UdJQQM +MAoGCCsGAQUFBwMfMA4GA1UdDwEB/wQEAwIHgDBmBggrBgEFBQcBAQRaMFgwIwYI +KwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmVudHJ1c3QubmV0MDEGCCsGAQUFBzAChiVo +dHRwOi8vYWlhLmVudHJ1c3QubmV0L3ZtYzEtY2hhaW4uY2VyMDIGA1UdHwQrMCkw +J6AloCOGIWh0dHA6Ly9jcmwuZW50cnVzdC5uZXQvdm1jMWNhLmNybDBPBgNVHSAE +SDBGMDYGCmCGSAGG+mwKAQswKDAmBggrBgEFBQcCARYaaHR0cDovL3d3dy5lbnRy +dXN0Lm5ldC9ycGEwDAYKKwYBBAGDnl8BATAfBgNVHSMEGDAWgBSLtjl20DSQpj9i +4WTqPrz0fEahczAdBgNVHQ4EFgQUxAJ+yoDhzpPUzAPWKBYxg108dU0wCQYDVR0T +BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAnqdB/vcwxFcxAlyCK0W5HOthXUdXRg9a +GwPDupqmLq2rKfyysZXonJJfr8jqO0f3l6TWTTJlXHljAwwXMtg3T3ngLyEzip5p +g0zH7s5eXjmWRhOeuHt21o611bXDbUNFTF0IpbYBTgOwAz/+k3XLVehf8dW7Y0Lr +VkzxJ6U82NxmqjaAnkm+H127x5/jPAr4LLD4gZfqFaHzw/ZLoS+fXFGs+dpuYE4s +n+xe0msYMu8qWABiMGA+MCKl45Dp5di+c2fyXtKyQ3rKI8XXZ0nN4bXK7DZd+3E3 +kbpmR6cDliloU808Bi/erMkrfUHRoZ2d586lkmwkLcoDkJ/yPD+Jhw== +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + extn_list = [] + + for extn in asn1Object['tbsCertificate']['extensions']: + extn_list.append(extn['extnID']) + + if extn['extnID'] == rfc3709.id_pe_logotype: + s = extn['extnValue'] + logotype, rest = der_decoder(s, rfc3709.LogotypeExtn()) + self.assertFalse(rest) + + self.assertTrue(logotype.prettyPrint()) + self.assertEqual(s, der_encoder(logotype)) + + ids = logotype['subjectLogo']['direct']['image'][0]['imageDetails'] + + self.assertEqual("image/svg+xml", ids['mediaType']) + self.assertEqual( + "data:image/svg+xml;base64", ids['logotypeURI'][0][0:25]) + + self.assertIn(rfc3709.id_pe_logotype, extn_list) + + def testExtensionsMap(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] in rfc5280.certificateExtensionsMap.keys(): + extnValue, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc3739.py b/tests/test_rfc3739.py new file mode 100644 index 0000000..3c4ce3a --- /dev/null +++ b/tests/test_rfc3739.py @@ -0,0 +1,126 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1.type import error +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc3739 + + +class QCCertificateTestCase(unittest.TestCase): + pem_text = """\ +MIIFLTCCBBWgAwIBAgIMVRaIE9MInBkG6aUaMA0GCSqGSIb3DQEBCwUAMHMxCzAJ +BgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRowGAYDVQQLExFG +b3IgRGVtbyBVc2UgT25seTEtMCsGA1UEAxMkR2xvYmFsU2lnbiBEZW1vIElzc3Vp +bmcgQ0EgLSBTdGFnaW5nMB4XDTE4MDYxNTA1MTgxNFoXDTE5MDYxNjA1MTgxNFow +WjELMAkGA1UEBhMCQkUxGTAXBgNVBAMTEFRlc3QgQ2VydGlmaWNhdGUxEjAQBgNV +BAUTCTEyMzQ1Njc4OTENMAsGA1UEKhMEVGVzdDENMAsGA1UEBBMEVGVzdDCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL/tsE2EIVQhpkZU5XmFR6FAq9ou +k8FWbyku5M7S2JT3c6OFMQiVgu6nfqdsl4rzojhUXQtMOnO7sUqcIedmwqRIR/jd +X+ELqGGRHodZt94Tjf6Qgn2Wv/EgG0EIwsOAisGKr4qTNs6ZmVMqQ3I4+l9Ik5eM +whr9JfrhSxrXDzoh8Prc9lNjQbk+YKXw0zLmVxW7GAu9zTr98GF+HapIhNQbvqOc +fHoY5svla5MqoRXagfrw/w2fSaO/LT+AFsZYODVpvCg/X3xsknoG7TDIeZ8Hmlgq +Mvg9l9VA2JbSv1C38SeOm0Hfv0l0fspZPSrtmbYlvBtQoO1X/GhQXvE7UvMCAwEA +AaOCAdgwggHUMA4GA1UdDwEB/wQEAwIGQDCBkQYIKwYBBQUHAQEEgYQwgYEwQQYI +KwYBBQUHMAKGNWh0dHA6Ly9zZWN1cmUuc3RhZ2luZy5nbG9iYWxzaWduLmNvbS9n +c2RlbW9zaGEyZzMuY3J0MDwGCCsGAQUFBzABhjBodHRwOi8vb2NzcDIuc3RhZ2lu +Zy5nbG9iYWxzaWduLmNvbS9nc2RlbW9zaGEyZzMwWQYDVR0gBFIwUDBDBgsrBgEE +AaAyASgjAjA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5nbG9iYWxzaWduLmNv +bS9yZXBvc2l0b3J5LzAJBgcEAIvsQAECMAkGA1UdEwQCMAAwQwYDVR0fBDwwOjA4 +oDagNIYyaHR0cDovL2NybC5zdGFnaW5nLmdsb2JhbHNpZ24uY29tL2dzZGVtb3No +YTJnMy5jcmwwLQYIKwYBBQUHAQMEITAfMAgGBgQAjkYBATATBgYEAI5GAQYwCQYH +BACORgEGATAUBgNVHSUEDTALBgkqhkiG9y8BAQUwHQYDVR0OBBYEFNRFutzxY2Jg +qilbYWe86em0QQC+MB8GA1UdIwQYMBaAFBcYifCc7R2iN5qLgGGRDT/RWZN6MA0G +CSqGSIb3DQEBCwUAA4IBAQCMJeiaEAu45PetKSoPEnJ5t4MYr4dUl/HdnV13WEUW +/34yHDGuubTFqJ6sM7P7dO25kdNOr75mR8yc0+gsGJv5K5C7LXfk36ofDlVQm0RJ +3LTRhCvnJIzvuc5R52QW3MvB0EEPd1sfkpGgyTdK8zYZkwCXrWgMuPhBG/kgTiN0 +65qitL/WfkcX9SXmsYuV1a3Tsxz+6/rTtxdZfXSJgaVCOWHGyXCvpAQM/4eH5hSj +UfTNwEMrE4sw4k9F90Sp8Wx24sMRDTIpnEXh3ceZSzBN2OYCIO84GaiZDpSvvkYN +Iwtui+Wql/HveMqbAtXkiv9GDXYZms3HBoIaCVuDaUf6 +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + count = 0 + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc3739.id_pe_qcStatements: + s = extn['extnValue'] + qc_stmts, rest = der_decoder(s, rfc3739.QCStatements()) + self.assertFalse(rest) + self.assertTrue(qc_stmts.prettyPrint()) + self.assertEqual(s, der_encoder(qc_stmts)) + + for qcs in qc_stmts: + count += 1 + + self.assertEqual(2, count) + + def testExtensionsMap(self): + + class SequenceOfOID(univ.SequenceOf): + componentType = univ.ObjectIdentifier() + + openTypesMap = { + univ.ObjectIdentifier('0.4.0.1862.1.6'): SequenceOfOID() + } + + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + count = 0 + found_qc_stmt_oid = False + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc3739.id_pe_qcStatements: + qc_stmts, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']], + openTypes=openTypesMap, + decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(qc_stmts.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(qc_stmts)) + + for qcs in qc_stmts: + count += 1 + if qcs['statementId'] in openTypesMap.keys(): + for oid in qcs['statementInfo']: + if oid == univ.ObjectIdentifier('0.4.0.1862.1.6.1'): + found_qc_stmt_oid = True + + self.assertEqual(2, count) + self.assertTrue(found_qc_stmt_oid) + +class WithComponentsTestCase(unittest.TestCase): + + def testDerCodec(self): + si = rfc3739.SemanticsInformation() + self.assertRaises(error.PyAsn1Error, der_encoder, si) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc3770.py b/tests/test_rfc3770.py new file mode 100644 index 0000000..667ab24 --- /dev/null +++ b/tests/test_rfc3770.py @@ -0,0 +1,95 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.compat.octets import str2octs + +from pyasn1_modules import pem +from pyasn1_modules import rfc5480 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc3770 + + +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_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + sig_alg = asn1Object['tbsCertificate']['signature'] + + self.assertEqual(rfc5480.ecdsa_with_SHA384, sig_alg['algorithm']) + self.assertFalse(sig_alg['parameters'].hasValue()) + + spki_alg = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + + self.assertEqual(rfc5480.id_ecPublicKey, spki_alg['algorithm']) + self.assertEqual( + rfc5480.secp384r1, spki_alg['parameters']['namedCurve']) + + extn_list = [] + for extn in asn1Object['tbsCertificate']['extensions']: + extn_list.append(extn['extnID']) + if extn['extnID'] in rfc5280.certificateExtensionsMap.keys(): + extnValue, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + if extn['extnID'] == rfc3770.id_pe_wlanSSID: + self.assertIn(str2octs('Example'), extnValue) + + if extn['extnID'] == rfc5280.id_ce_extKeyUsage: + self.assertIn(rfc3770.id_kp_eapOverLAN, extnValue) + self.assertIn(rfc3770.id_kp_eapOverPPP, extnValue) + + self.assertIn(rfc3770.id_pe_wlanSSID, extn_list) + self.assertIn(rfc5280.id_ce_extKeyUsage, extn_list) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc3779.py b/tests/test_rfc3779.py new file mode 100644 index 0000000..652826e --- /dev/null +++ b/tests/test_rfc3779.py @@ -0,0 +1,98 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der import decoder as der_decoder +from pyasn1.codec.der import encoder as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc3779 + + +class CertificateExtnTestCase(unittest.TestCase): + pem_text = """\ +MIIECjCCAvKgAwIBAgICAMkwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLcmlw +ZS1uY2MtdGEwIBcNMTcxMTI4MTQzOTU1WhgPMjExNzExMjgxNDM5NTVaMBYxFDAS +BgNVBAMTC3JpcGUtbmNjLXRhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA0URYSGqUz2myBsOzeW1jQ6NsxNvlLMyhWknvnl8NiBCs/T/S2XuNKQNZ+wBZ +xIgPPV2pFBFeQAvoH/WK83HwA26V2siwm/MY2nKZ+Olw+wlpzlZ1p3Ipj2eNcKrm +it8BwBC8xImzuCGaV0jkRB0GZ0hoH6Ml03umLprRsn6v0xOP0+l6Qc1ZHMFVFb38 +5IQ7FQQTcVIxrdeMsoyJq9eMkE6DoclHhF/NlSllXubASQ9KUWqJ0+Ot3QCXr4LX +ECMfkpkVR2TZT+v5v658bHVs6ZxRD1b6Uk1uQKAyHUbn/tXvP8lrjAibGzVsXDT2 +L0x4Edx+QdixPgOji3gBMyL2VwIDAQABo4IBXjCCAVowHQYDVR0OBBYEFOhVKx/W +0aT35ATG2OVoDR68Fj/DMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG +MIGxBggrBgEFBQcBCwSBpDCBoTA8BggrBgEFBQcwCoYwcnN5bmM6Ly9ycGtpLnJp +cGUubmV0L3JlcG9zaXRvcnkvcmlwZS1uY2MtdGEubWZ0MDIGCCsGAQUFBzANhiZo +dHRwczovL3JyZHAucmlwZS5uZXQvbm90aWZpY2F0aW9uLnhtbDAtBggrBgEFBQcw +BYYhcnN5bmM6Ly9ycGtpLnJpcGUubmV0L3JlcG9zaXRvcnkvMBgGA1UdIAEB/wQO +MAwwCgYIKwYBBQUHDgIwJwYIKwYBBQUHAQcBAf8EGDAWMAkEAgABMAMDAQAwCQQC +AAIwAwMBADAhBggrBgEFBQcBCAEB/wQSMBCgDjAMMAoCAQACBQD/////MA0GCSqG +SIb3DQEBCwUAA4IBAQAVgJjrZ3wFppC8Yk8D2xgzwSeWVT2vtYq96CQQsjaKb8nb +eVz3DwcS3a7RIsevrNVGo43k3AGymg1ki+AWJjvHvJ+tSzCbn5+X6Z7AfYTf2g37 +xINVDHru0PTQUargSMBAz/MBNpFG8KThtT7WbJrK4+f/lvx0m8QOlYm2a17iXS3A +GQJ6RHcq9ADscqGdumxmMMDjwED26bGaYdmru1hNIpwF//jVM/eRjBFoPHKFlx0k +Ld/yoCQNmx1kW+xANx4uyWxi/DYgSV7Oynq+C60OucW+d8tIhkblh8+YfrmukJds +V+vo2L72yerdbsP9xjqvhZrLKfsLZjYK4SdYYthi +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + + substrate = pem.readBase64fromText(self.pem_text) + + asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + extn_list = [] + for extn in asn1Object['tbsCertificate']['extensions']: + extn_list.append(extn['extnID']) + + if extn['extnID'] == rfc3779.id_pe_ipAddrBlocks: + s = extn['extnValue'] + addr_blocks, rest = der_decoder.decode(s, rfc3779.IPAddrBlocks()) + self.assertFalse(rest) + self.assertTrue(addr_blocks.prettyPrint()) + self.assertEqual(s, der_encoder.encode(addr_blocks)) + + if extn['extnID'] == rfc3779.id_pe_autonomousSysIds: + s = extn['extnValue'] + as_ids, rest = der_decoder.decode(s, rfc3779.ASIdentifiers()) + self.assertFalse(rest) + self.assertTrue(as_ids.prettyPrint()) + self.assertEqual(s, der_encoder.encode(as_ids)) + + self.assertIn(rfc3779.id_pe_ipAddrBlocks, extn_list) + self.assertIn(rfc3779.id_pe_autonomousSysIds, extn_list) + + def testExtensionsMap(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + for extn in asn1Object['tbsCertificate']['extensions']: + if (extn['extnID'] == rfc3779.id_pe_ipAddrBlocks or + extn['extnID'] == rfc3779.id_pe_autonomousSysIds): + extnValue, rest = der_decoder.decode( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + self.assertEqual(extn['extnValue'], der_encoder.encode(extnValue)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc3820.py b/tests/test_rfc3820.py new file mode 100644 index 0000000..0895b28 --- /dev/null +++ b/tests/test_rfc3820.py @@ -0,0 +1,78 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc3820 + + +class ProxyCertificateTestCase(unittest.TestCase): + pem_text = """\ +MIID9DCCAtygAwIBAgIEDODd4TANBgkqhkiG9w0BAQUFADCBjTESMBAGCgmSJomT +8ixkARkWAm5sMRcwFQYKCZImiZPyLGQBGRYHZS1pbmZyYTEaMBgGA1UEChMRVHJh +aW5pbmcgU2VydmljZXMxDjAMBgNVBAsTBXVzZXJzMRowGAYDVQQLExFTZWN1cml0 +eSBUcmFpbmluZzEWMBQGA1UEAxMNUGlldGplIFB1ayA0MjAeFw0xOTExMjcwODMz +NDZaFw0xOTExMjcyMDM4NDZaMIGhMRIwEAYKCZImiZPyLGQBGRYCbmwxFzAVBgoJ +kiaJk/IsZAEZFgdlLWluZnJhMRowGAYDVQQKExFUcmFpbmluZyBTZXJ2aWNlczEO +MAwGA1UECxMFdXNlcnMxGjAYBgNVBAsTEVNlY3VyaXR5IFRyYWluaW5nMRYwFAYD +VQQDEw1QaWV0amUgUHVrIDQyMRIwEAYDVQQDEwkyMTYwNjM0NTcwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCu2b1j1XQXAgNazmTtdp6jjzvNQT8221/c +dSIv2ftxr3UochHbazTfoR7wDT5PGlp2v99M0kZQvAEJ96CJpBDte4pwio7xHK3w +s5h7lH3W2ydrxAMSnZp0NHxyo3DNenTV5HavGjraOZDLt/k1aPJ8C68CBbrGDQxH +wzTs21Z+7lAy4C1ZNyOhkNF4qD5qy9Q2SHOPD+uc2QZE8IadZyxbeW/lEWHjESI1 +5y55oLZhe3leb2NswvppgdwM8KW4Pbtya6mDKGH4e1qQfNfxsqlxbIBr4UaM8iSM +5BhJhe7VCny2iesGCJWz3NNoTJKBehN5o2xs7+fHv+sOW2Yuc3MnAgMBAAGjRjBE +MBMGA1UdJQQMMAoGCCsGAQUFBwMCMA4GA1UdDwEB/wQEAwIEsDAdBggrBgEFBQcB +DgEB/wQOMAwwCgYIKwYBBQUHFQEwDQYJKoZIhvcNAQEFBQADggEBAJbeKv3yQ9Yc +GHT4r64gVkKd4do7+cRS9dfWg8pcLRn3aBzTCBIznkg+OpzjteOJCuw6AxDsDPmf +n0Ms7LaAqegW8vcYgcZTxeABE5kgg5HTMUSMo39kFNTYHlNgsVfnOhpePnWX+e0Y +gPpQU7w1npAhr23lXn9DNWgWMMT6T3z+NngcJ9NQdEee9D4rzY5Oo9W/2OAPuMne +w5dGF7wVCUBRi6vrMnWYN8E3sHiFDJJrOsPWZzjRCa/W3N9A/OdgjitKQc3X4dlS +tP2J7Yxv/B/6+VxVEa9WtVXsm/wJnhwvICBscB1/4WkI0PfJ7Nh4ZqQplPdlDEKe +FOuri/fKBe0= +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + found_ppl = False + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc3820.id_pe_proxyCertInfo: + self.assertTrue(rfc3820.id_pe_proxyCertInfo in rfc5280.certificateExtensionsMap.keys()) + pci, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[rfc3820.id_pe_proxyCertInfo]) + self.assertFalse(rest) + self.assertTrue(pci.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(pci)) + + self.assertEqual(rfc3820.id_ppl_inheritAll, pci['proxyPolicy']['policyLanguage']) + found_ppl = True + + self.assertTrue(found_ppl) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc3852.py b/tests/test_rfc3852.py new file mode 100644 index 0000000..56b25cc --- /dev/null +++ b/tests/test_rfc3852.py @@ -0,0 +1,128 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc3852 +from pyasn1_modules import rfc6402 + + +class ContentInfoTestCase(unittest.TestCase): + pem_text = """\ +MIIEJQYJKoZIhvcNAQcCoIIEFjCCBBICAQMxCzAJBgUrDgMCGgUAMIIDAgYIKwYBBQUHDAKgggL0 +BIIC8DCCAuwweDB2AgECBgorBgEEAYI3CgoBMWUwYwIBADADAgEBMVkwVwYJKwYBBAGCNxUUMUow +SAIBBQwZcGl0dWNoYTEuZW1lYS5ocHFjb3JwLm5ldAwMRU1FQVxwaXR1Y2hhDBpDTUNSZXFHZW5l +cmF0b3IudnNob3N0LmV4ZTCCAmqgggJmAgEBMIICXzCCAcgCAQAwADCBnzANBgkqhkiG9w0BAQEF +AAOBjQAwgYkCgYEA0jm7SSSm2wyEAzuNKtFZFJKo91SrJq9wQwEhEKHDavZwMQOm1rZ2PF8NWCEb +PqrhToQ7rtiGLSZa4dF4bzgmBqQ9aoSfEX4jISt31Vy+skHidXjHHpbsjT24NPhrZgANivL7CxD6 +Ft+s7qS1gL4HRm2twQkqSwOLrE/q2QeXl2UCAwEAAaCCAR0wGgYKKwYBBAGCNw0CAzEMFgo2LjIu +OTIwMC4yMD4GCSqGSIb3DQEJDjExMC8wHQYDVR0OBBYEFMW2skn88gxhONWZQA4sWGBDb68yMA4G +A1UdDwEB/wQEAwIHgDBXBgkrBgEEAYI3FRQxSjBIAgEFDBlwaXR1Y2hhMS5lbWVhLmhwcWNvcnAu +bmV0DAxFTUVBXHBpdHVjaGEMGkNNQ1JlcUdlbmVyYXRvci52c2hvc3QuZXhlMGYGCisGAQQBgjcN +AgIxWDBWAgECHk4ATQBpAGMAcgBvAHMAbwBmAHQAIABTAHQAcgBvAG4AZwAgAEMAcgB5AHAAdABv +AGcAcgBhAHAAaABpAGMAIABQAHIAbwB2AGkAZABlAHIDAQAwDQYJKoZIhvcNAQEFBQADgYEAJZlu +mxjtCxSOQi27jsVdd3y8NSIlzNv0b3LqmzvAly6L+CstXcnuG2MPQqPH9R7tbJonGUniBQO9sQ7C +KhYWj2gfhiEkSID82lV5chINVUFKoUlSiEhWr0tPGgvOaqdsKQcrHfzrsBbFkhDqrFSVy7Yivbnh +qYszKrOjJKiiCPMwADAAMYH5MIH2AgEDgBTFtrJJ/PIMYTjVmUAOLFhgQ2+vMjAJBgUrDgMCGgUA +oD4wFwYJKoZIhvcNAQkDMQoGCCsGAQUFBwwCMCMGCSqGSIb3DQEJBDEWBBTFTkK/OifaFjwqHiJu +xM7qXcg/VzANBgkqhkiG9w0BAQEFAASBgKfC6jOi1Wgy4xxDCQVK9+e5tktL8wE/j2cb9JSqq+aU +5UxEgXEw7q7BoYZCAzcxMRriGzakXr8aXHcgkRJ7XcFvLPUjpmGg9SOZ2sGW4zQdWAwImN/i8loc +xicQmJP+VoMHo/ZpjFY9fYCjNZUArgKsEwK/s+p9yrVVeB1Nf8Mn +""" + + def setUp(self): + self.asn1Spec = rfc3852.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + + layers = { + rfc3852.id_ct_contentInfo: rfc3852.ContentInfo(), + rfc3852.id_signedData: rfc3852.SignedData(), + rfc6402.id_cct_PKIData: rfc6402.PKIData() + } + + getNextLayer = { + rfc3852.id_ct_contentInfo: lambda x: x['contentType'], + rfc3852.id_signedData: lambda x: x['encapContentInfo']['eContentType'], + rfc6402.id_cct_PKIData: lambda x: None + } + + getNextSubstrate = { + rfc3852.id_ct_contentInfo: lambda x: x['content'], + rfc3852.id_signedData: lambda x: x['encapContentInfo']['eContent'], + rfc6402.id_cct_PKIData: lambda x: None + } + + alg_oids = ( + univ.ObjectIdentifier('1.3.14.3.2.26'), + univ.ObjectIdentifier('1.2.840.113549.1.1.1'), + univ.ObjectIdentifier('1.2.840.113549.1.1.5'), + univ.ObjectIdentifier('1.2.840.113549.1.1.11'), + ) + + encoded_null = der_encoder(univ.Null("")) + + next_layer = rfc3852.id_ct_contentInfo + + count = 0 + + while next_layer: + asn1Object, rest = der_decoder(substrate, asn1Spec=layers[next_layer]) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + if next_layer == rfc3852.id_signedData: + for d in asn1Object['digestAlgorithms']: + self.assertIn(d['algorithm'], alg_oids) + self.assertEqual(encoded_null, d['parameters']) + count += 1 + + for si in asn1Object['signerInfos']: + self.assertIn(si['digestAlgorithm']['algorithm'], alg_oids) + self.assertEqual( + encoded_null, si['digestAlgorithm']['parameters']) + count += 1 + + self.assertIn(si['signatureAlgorithm']['algorithm'], alg_oids) + self.assertEqual( + encoded_null, si['signatureAlgorithm']['parameters']) + count += 1 + + if next_layer == rfc6402.id_cct_PKIData: + for req in asn1Object['reqSequence']: + cr = req['tcr']['certificationRequest'] + self.assertIn(cr['signatureAlgorithm']['algorithm'], alg_oids) + self.assertEqual( + encoded_null, cr['signatureAlgorithm']['parameters']) + count += 1 + + cri_spki = cr['certificationRequestInfo']['subjectPublicKeyInfo'] + self.assertIn(cri_spki['algorithm']['algorithm'], alg_oids) + self.assertEqual( + encoded_null, cri_spki['algorithm']['parameters']) + count += 1 + + substrate = getNextSubstrate[next_layer](asn1Object) + next_layer = getNextLayer[next_layer](asn1Object) + + self.assertEqual(5, count) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc4010.py b/tests/test_rfc4010.py new file mode 100644 index 0000000..7474b9d --- /dev/null +++ b/tests/test_rfc4010.py @@ -0,0 +1,136 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc4010 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5751 + + +class EnvelopedDataTestCase(unittest.TestCase): + env_data_pem_text = """\ +MIIFewYJKoZIhvcNAQcDoIIFbDCCBWgCAQIxUqJQAgEEMCMEEKBBI2KxDUPS5TCo +RCEDJo4YDzIwMTkwOTEyMTIwMDAwWjAMBgoqgxqMmkQHAQEBBBipFE2DxCLAx2Og +E53Jt21V8kAoscU7K3wwggUNBgkqhkiG9w0BBwEwHAYIKoMajJpEAQQEEEJPR1VT +SVZfQk9HVVNJViGAggTgc8exehjJD/gtEOIrg6tK5Emaa4PJ7l8f+EtyDD/ffQay +XVAGz2MXUIQMEzmSLrnsr9NEyXvxGpvcsi7mV8tDxZU0YuyhA/C/HMh7EaBKG1hj +C7xNw+IRIUxrbRJakMQbzMWWYJupC5zRu4/Ge9i+JVOGgES2E0L5LZSZ53wmnHA0 +ols1PHl3F3Z2QM3CkewqA3NP1waXQ0XXb0Oyl6Gq12B7ksm7euPWA3KctEjfYBD6 +nBT6wQd57rAMeFTk5aceWd2Sb/0xMpjfCg6GzX8pAWVEU8LqTvVmlSWdx3f3fAtU +giZ+gx7jNY8A6duln8zvMQn3mtPDCa50GzSrAx8JreHRWSDr3Dp8EfJzUgfy7dWl +I9xs5bh1TMkEMk+AHWQ5sBXTZkDgVAS5m1mIbXe7dzuxKsfGxjWu1eyy9J77mtOG +o9aAOqYfxv/I8YQcgWHTeQcIO39Rmt2QsI7trRaEJ1jgj2E1To5gRCbIQWzQuyoS +6affgu/9dwPXCAt0+0XrnO5vhaKX/RWm7ve8hYsiT0vI0hdBJ3rDRkdS9VL6NlnX +OuohAqEq8b3s2koBigdri052hceAElTHD+4A4qRDiMLlFLlQqoJlpBwCtEPZsIQS +y62K7J/Towxxab5FoFjUTC5f79xPQPoKxYdgUB5AeAu5HgdWTn49Uqg4v/spTPSN +RTmDMVVyZ9qhzJfkDpH3TKCAE5t59w4gSPe/7l+MeSml9O+L9HTd9Vng3LBbIds3 +uQ4cfLyyQmly81qpJjR1+Rvwo46hOm0kf2sIFi0WULmP/XzLw6b1SbiHf/jqFg7T +FTyLMkPMPMmc7/kpLmYbKyTB4ineasTUL+bDrwu+uSzFAjTcI+1sz4Wo4p7RVywB +DKSI5Ocbd3iMt4XWJWtz0KBX6nBzlV+BBTCwaGMAU4IpPBYOuvcl7TJWx/ODBjbO +4zm4T/66w5IG3tKpsVMs4Jtrh8mtVXCLTBmKDzyjBVN2X8ALGXarItRgLa7k80lJ +jqTHwKCjiAMmT/eh67KzwmqBq5+8rJuXkax0NoXcDu6xkCMNHUQBYdnskaJqC2pu +8hIsPTOrh7ieYSEuchFvu7lI0E+p7ypW65CMiy+Y/Rm5OWeHzjKkU5AbPtx/Me2v +pQRCgaPwciZunx2Ivi1+WYUBU1pGNDO7Xz7a8UHbDURkh7b+40uz2d7YQjKgrZBv +6YwLAmw1LTE4bT9PM9n7LROnX8u6ksei8yiw8gZeVu+plWHbF+0O9siKAgxZlBna +0XFgPpdzjMDTS/sfTIYXWlFj7camhsmTDRjo5G2B212evaKmKgh5ALLSFSk86ZN5 +KvQvcfsp81jvJCBmDStrsUgSMzy0Og2quHOd61hRTVlYzwvJvfMzHGKdIWwYUbHZ +OKo/KLEk3E36U9PkPoZGEL2ZeCH4F9Wh3mgg0knBfEmlPnGexmBby6NXGK7VW3l6 +xcJlpdMaXKNVMfl2YK8k/34Hyft06KaYLEJsxAqk1pmLEmGhdZC1OAqovVB/1agS +zpMMaB9OWWqNsTjDc7tkDt8BZ72NsAbCI9XmsX81W+NqPb6Ju1dtI09bn113LX/Z +bOSdVicQcXSpl0FnTZaHgHJdQLcU28O7yFFOblqrvcMKpctdTA1TwG9LXEFttGrl +pgjZF3edo0Cez10epK+S +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.env_data_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_envelopedData, asn1Object['contentType']) + + ed, rest = der_decoder(asn1Object['content'], rfc5652.EnvelopedData()) + self.assertFalse(rest) + self.assertTrue(ed.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(ed)) + + kwa = ed['recipientInfos'][0]['kekri']['keyEncryptionAlgorithm'] + self.assertEqual(rfc4010.id_npki_app_cmsSeed_wrap, kwa['algorithm']) + + cea = ed['encryptedContentInfo']['contentEncryptionAlgorithm'] + self.assertEqual(rfc4010.id_seedCBC, cea['algorithm']) + param, rest = der_decoder( + cea['parameters'], asn1Spec=rfc4010.SeedCBCParameter()) + self.assertFalse(rest) + self.assertTrue(param.prettyPrint()) + self.assertEqual(cea['parameters'], der_encoder(param)) + + iv = univ.OctetString(hexValue='424f47555349565f424f475553495621') + self.assertEqual(iv, param) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.env_data_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertTrue(asn1Object['contentType'] in rfc5652.cmsContentTypesMap.keys()) + + kekri = asn1Object['content']['recipientInfos'][0]['kekri'] + kwa = kekri['keyEncryptionAlgorithm'] + self.assertEqual(rfc4010.id_npki_app_cmsSeed_wrap, kwa['algorithm']) + + eci = asn1Object['content']['encryptedContentInfo'] + cea = eci['contentEncryptionAlgorithm'] + self.assertEqual(rfc4010.id_seedCBC, cea['algorithm']) + + iv = univ.OctetString(hexValue='424f47555349565f424f475553495621') + self.assertEqual(iv, cea['parameters']) + +class SMIMECapabilitiesTestCase(unittest.TestCase): + smime_capabilities_pem_text = "MB4wDAYIKoMajJpEAQQFADAOBgoqgxqMmkQHAQEBBQA=" + + def setUp(self): + self.asn1Spec = rfc5751.SMIMECapabilities() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.smime_capabilities_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + alg_oid_list = [ ] + for cap in asn1Object: + self.assertTrue(cap['parameters'].hasValue()) + self.assertEqual(cap['parameters'], der_encoder(rfc4010.SeedSMimeCapability(""))) + alg_oid_list.append(cap['capabilityID']) + + self.assertIn(rfc4010.id_seedCBC, alg_oid_list) + self.assertIn(rfc4010.id_npki_app_cmsSeed_wrap, alg_oid_list) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) + diff --git a/tests/test_rfc4043.py b/tests/test_rfc4043.py new file mode 100644 index 0000000..0ab72dd --- /dev/null +++ b/tests/test_rfc4043.py @@ -0,0 +1,118 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc4043 + + +class PermIdCertTestCase(unittest.TestCase): + cert_pem_text = """\ +MIIDDTCCApOgAwIBAgIJAKWzVCgbsG5HMAoGCCqGSM49BAMDMD8xCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9n +dXMgQ0EwHhcNMTkxMTEwMDA0MDIyWhcNMjAxMTA5MDA0MDIyWjBNMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xEDAOBgNVBAoTB0V4 +YW1wbGUxDTALBgNVBAMTBEdhaWwwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQBoktg +/68xL+uEQaWBoHyOjw8EMLeMEng3R2H7yiEzTGoaMJgPOKvSfzB2P0paHYPL+B5y +Gc0CK5EHRujMl9ljH+Wydpk57rKBLo1ZzpWUS6anLGIkWs1sOakcgGGr7hGjggFL +MIIBRzAdBgNVHQ4EFgQU1pCNZuMzfEaJ9GGhH7RKy6Mvz+cwbwYDVR0jBGgwZoAU +8jXbNATapVXyvWkDmbBi7OIVCMGhQ6RBMD8xCzAJBgNVBAYTAlVTMQswCQYDVQQI +DAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0GCCQDokdYG +kU/O8jAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBhjBCBglghkgBhvhCAQ0E +NRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUgdHJ1c3RlZCBmb3IgYW55IHB1 +cnBvc2UuMFMGA1UdEQRMMEqgNgYIKwYBBQUHCAOgKjAoDBs4MjYyMDgtNDE3MDI4 +LTU0ODE5NS0yMTUyMzMGCSsGAQQBgaxgMIEQZ2FpbEBleGFtcGxlLmNvbTAKBggq +hkjOPQQDAwNoADBlAjBT+36Y/LPaGSu+61P7kR97M8jAjtH5DtUwrWR02ChshvYJ +x0bpZq3PJaO0WlBgFicCMQCf+67wSvjxxtjI/OAg4t8NQIJW1LcehSXizlPDc772 +/FC5OiUAxO+iFaSVMeDFsCo= +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + perm_id_oid = rfc4043.id_on_permanentIdentifier + assigner_oid = univ.ObjectIdentifier('1.3.6.1.4.1.22112.48') + permanent_identifier_found = False + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectAltName: + extnValue, rest = der_decoder( + extn['extnValue'], asn1Spec=rfc5280.SubjectAltName()) + + self.assertFalse(rest) + self.assertTrue(extnValue.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + for gn in extnValue: + if gn['otherName'].hasValue(): + self.assertEqual(perm_id_oid, gn['otherName']['type-id']) + + onValue, rest = der_decoder( + gn['otherName']['value'], + asn1Spec=rfc4043.PermanentIdentifier()) + + self.assertFalse(rest) + self.assertTrue(onValue.prettyPrint()) + self.assertEqual(gn['otherName']['value'], der_encoder(onValue)) + self.assertEqual(assigner_oid, onValue['assigner']) + permanent_identifier_found = True + + self.assertTrue(permanent_identifier_found) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + perm_id_oid = rfc4043.id_on_permanentIdentifier + assigner_oid = univ.ObjectIdentifier('1.3.6.1.4.1.22112.48') + permanent_identifier_found = False + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectAltName: + extnValue, rest = der_decoder( + extn['extnValue'], asn1Spec=rfc5280.SubjectAltName(), + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(extnValue.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + for gn in extnValue: + if gn['otherName'].hasValue(): + on = gn['otherName'] + self.assertEqual(perm_id_oid, on['type-id']) + self.assertEqual(assigner_oid, on['value']['assigner']) + permanent_identifier_found = True + + self.assertTrue(permanent_identifier_found) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc4055.py b/tests/test_rfc4055.py new file mode 100755 index 0000000..cf0b376 --- /dev/null +++ b/tests/test_rfc4055.py @@ -0,0 +1,181 @@ +# +# 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 +import unittest + +from pyasn1.codec.der import decoder as der_decoder +from pyasn1.codec.der import encoder as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc4055 + + +class PSSDefautTestCase(unittest.TestCase): + pss_default_pem_text = "MAsGCSqGSIb3DQEBCg==" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pss_default_pem_text) + asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertTrue(rfc4055.id_RSASSA_PSS, asn1Object[0]) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pss_default_pem_text) + asn1Object, rest = der_decoder.decode(substrate, + asn1Spec=self.asn1Spec, + decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + self.assertFalse(asn1Object['parameters'].hasValue()) + + +class PSSSHA512TestCase(unittest.TestCase): + pss_sha512_pem_text = "MDwGCSqGSIb3DQEBCjAvoA8wDQYJYIZIAWUDBAIDBQChHDAaBg" \ + "kqhkiG9w0BAQgwDQYJYIZIAWUDBAIDBQA=" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pss_sha512_pem_text) + asn1Object, rest = der_decoder.decode( + substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertTrue(rfc4055.id_RSASSA_PSS, asn1Object[0]) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pss_sha512_pem_text) + asn1Object, rest = der_decoder.decode( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + self.assertTrue(asn1Object['parameters'].hasValue()) + self.assertTrue(20, asn1Object['parameters']['saltLength']) + + +class OAEPDefautTestCase(unittest.TestCase): + oaep_default_pem_text = "MAsGCSqGSIb3DQEBBw==" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.oaep_default_pem_text) + asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertTrue(rfc4055.id_RSAES_OAEP, asn1Object[0]) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.oaep_default_pem_text) + asn1Object, rest = der_decoder.decode( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + self.assertFalse(asn1Object['parameters'].hasValue()) + + +class OAEPSHA256TestCase(unittest.TestCase): + oaep_sha256_pem_text = "MDwGCSqGSIb3DQEBBzAvoA8wDQYJYIZIAWUDBAIBBQChHDAaB" \ + "gkqhkiG9w0BAQgwDQYJYIZIAWUDBAIBBQA=" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.oaep_sha256_pem_text) + asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertTrue(rfc4055.id_RSAES_OAEP, asn1Object[0]) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.oaep_sha256_pem_text) + asn1Object, rest = der_decoder.decode( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + self.assertTrue(asn1Object['parameters'].hasValue()) + + oaep_p = asn1Object['parameters'] + + self.assertEqual(univ.Null(""), oaep_p['hashFunc']['parameters']) + self.assertEqual(univ.Null(""), oaep_p['maskGenFunc']['parameters']['parameters']) + + +class OAEPFullTestCase(unittest.TestCase): + oaep_full_pem_text = "MFMGCSqGSIb3DQEBBzBGoA8wDQYJYIZIAWUDBAICBQChHDAaBgk" \ + "qhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiFTATBgkqhkiG9w0BAQ" \ + "kEBmZvb2Jhcg==" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.oaep_full_pem_text) + asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + + self.assertTrue(rfc4055.id_RSAES_OAEP, asn1Object[0]) + + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.oaep_full_pem_text) + asn1Object, rest = der_decoder.decode(substrate, + asn1Spec=self.asn1Spec, + decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + self.assertTrue(asn1Object['parameters'].hasValue()) + + oaep_p = asn1Object['parameters'] + + self.assertEqual(univ.Null(""), oaep_p['hashFunc']['parameters']) + self.assertEqual( + univ.Null(""), oaep_p['maskGenFunc']['parameters']['parameters']) + self.assertEqual( + univ.OctetString(value='foobar'), + oaep_p['pSourceFunc']['parameters']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc4073.py b/tests/test_rfc4073.py new file mode 100644 index 0000000..4bd5e5f --- /dev/null +++ b/tests/test_rfc4073.py @@ -0,0 +1,146 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.compat.octets import str2octs + +from pyasn1_modules import pem +from pyasn1_modules import rfc2634 +from pyasn1_modules import rfc4073 +from pyasn1_modules import rfc5652 + + +class ContentCollectionTestCase(unittest.TestCase): + pem_text = """\ +MIIG/QYLKoZIhvcNAQkQAROgggbsMIIG6DCCAWcGCyqGSIb3DQEJEAEUoIIBVjCC +AVIwgfEGCSqGSIb3DQEHAaCB4wSB4ENvbnRlbnQtVHlwZTogdGV4dC9wbGFpbgoK +UkZDIDQwNzMsIHB1Ymxpc2hlZCBpbiBNYXkgMjAwNSwgZGVzY3JpYmVzIGEgY29u +dmVudGlvbiBmb3IgdXNpbmcgdGhlCkNyeXB0b2dyYXBoaWMgTWVzc2FnZSBTeW50 +YXggKENNUykgdG8gcHJvdGVjdCBhIGNvbnRlbnQgY29sbGVjdGlvbi4gIElmCmRl +c2lyZWQsIGF0dHJpYnV0ZXMgY2FuIGJlIGFzc29jaWF0ZWQgd2l0aCB0aGUgY29u +dGVudC4KMFwwMwYLKoZIhvcNAQkQAgQxJDAiDBVBYnN0cmFjdCBmb3IgUkZDIDQw +NzMGCSqGSIb3DQEHATAlBgsqhkiG9w0BCRACBzEWBBSkLSXBiRWvbwnJKb4EGb1X +FwCa3zCCBXkGCyqGSIb3DQEJEAEUoIIFaDCCBWQwggT9BgkqhkiG9w0BBwGgggTu +BIIE6kNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbgoKVGhlIGZvbGxvd2luZyBBU04u +MSBtb2R1bGUgZGVmaW5lcyB0aGUgc3RydWN0dXJlcyB0aGF0IGFyZSBuZWVkZWQg +dG8KaW1wbGVtZW50IHRoZSBzcGVjaWZpY2F0aW9uIGluIFJGQyA0MDczLiAgSXQg +aXMgZXhwZWN0ZWQgdG8gYmUgdXNlZCBpbgpjb25qdW5jdGlvbiB3aXRoIHRoZSBB +U04uMSBtb2R1bGVzIGluIFJGQyA1NjUyIGFuZCBSRkMgMzI3NC4KCiAgIENvbnRl +bnRDb2xsZWN0aW9uTW9kdWxlCiAgICAgeyBpc28oMSkgbWVtYmVyLWJvZHkoMikg +dXMoODQwKSByc2Fkc2koMTEzNTQ5KSBwa2NzKDEpCiAgICAgICBwa2NzLTkoOSkg +c21pbWUoMTYpIG1vZHVsZXMoMCkgMjYgfQoKICAgREVGSU5JVElPTlMgSU1QTElD +SVQgVEFHUyA6Oj0KICAgQkVHSU4KCiAgIElNUE9SVFMKICAgICBBdHRyaWJ1dGUs +IENvbnRlbnRJbmZvCiAgICAgICBGUk9NIENyeXB0b2dyYXBoaWNNZXNzYWdlU3lu +dGF4MjAwNCAtLSBbQ01TXQogICAgICAgICB7IGlzbygxKSBtZW1iZXItYm9keSgy +KSB1cyg4NDApIHJzYWRzaSgxMTM1NDkpCiAgICAgICAgICAgcGtjcygxKSBwa2Nz +LTkoOSkgc21pbWUoMTYpIG1vZHVsZXMoMCkgY21zLTIwMDEoMTQpIH07CgoKICAg +LS0gQ29udGVudCBDb2xsZWN0aW9uIENvbnRlbnQgVHlwZSBhbmQgT2JqZWN0IElk +ZW50aWZpZXIKCiAgIGlkLWN0LWNvbnRlbnRDb2xsZWN0aW9uIE9CSkVDVCBJREVO +VElGSUVSIDo6PSB7CiAgICAgICAgICAgaXNvKDEpIG1lbWJlci1ib2R5KDIpIHVz +KDg0MCkgcnNhZHNpKDExMzU0OSkgcGtjcygxKQogICAgICAgICAgIHBrY3M5KDkp +IHNtaW1lKDE2KSBjdCgxKSAxOSB9CgogICBDb250ZW50Q29sbGVjdGlvbiA6Oj0g +U0VRVUVOQ0UgU0laRSAoMS4uTUFYKSBPRiBDb250ZW50SW5mbwoKICAgLS0gQ29u +dGVudCBXaXRoIEF0dHJpYnV0ZXMgQ29udGVudCBUeXBlIGFuZCBPYmplY3QgSWRl +bnRpZmllcgoKICAgaWQtY3QtY29udGVudFdpdGhBdHRycyBPQkpFQ1QgSURFTlRJ +RklFUiA6Oj0gewogICAgICAgICAgIGlzbygxKSBtZW1iZXItYm9keSgyKSB1cyg4 +NDApIHJzYWRzaSgxMTM1NDkpIHBrY3MoMSkKICAgICAgICAgICBwa2NzOSg5KSBz +bWltZSgxNikgY3QoMSkgMjAgfQoKICAgQ29udGVudFdpdGhBdHRyaWJ1dGVzIDo6 +PSBTRVFVRU5DRSB7CiAgICAgICBjb250ZW50ICAgICBDb250ZW50SW5mbywKICAg +ICAgIGF0dHJzICAgICAgIFNFUVVFTkNFIFNJWkUgKDEuLk1BWCkgT0YgQXR0cmli +dXRlIH0KCiAgIEVORAowYTA4BgsqhkiG9w0BCRACBDEpMCcMGkFTTi4xIE1vZHVs +ZSBmcm9tIFJGQyA0MDczBgkqhkiG9w0BBwEwJQYLKoZIhvcNAQkQAgcxFgQUMbeK +buWO3egPDL8Kf7tBhzjIKLw= +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + + def test_layer(substrate, content_type): + asn1Object, rest = der_decoder(substrate, asn1Spec=layers[content_type]) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + if content_type == rfc4073.id_ct_contentWithAttrs: + for attr in asn1Object['attrs']: + self.assertIn(attr['attrType'], rfc5652.cmsAttributesMap) + + return asn1Object + + layers = rfc5652.cmsContentTypesMap + + getNextLayer = { + rfc5652.id_ct_contentInfo: lambda x: x['contentType'], + rfc4073.id_ct_contentCollection: lambda x: x[0]['contentType'], + rfc4073.id_ct_contentWithAttrs: lambda x: x['content']['contentType'], + rfc5652.id_data: lambda x: None, + } + + getNextSubstrate = { + rfc5652.id_ct_contentInfo: lambda x: x['content'], + rfc4073.id_ct_contentCollection: lambda x: x[0]['content'], + rfc4073.id_ct_contentWithAttrs: lambda x: x['content']['content'], + rfc5652.id_data: lambda x: None, + } + + substrate = pem.readBase64fromText(self.pem_text) + + this_layer = rfc5652.id_ct_contentInfo + + while this_layer != rfc5652.id_data: + if this_layer == rfc4073.id_ct_contentCollection: + asn1Object = test_layer(substrate, this_layer) + for ci in asn1Object: + substrate = ci['content'] + this_layer = ci['contentType'] + while this_layer != rfc5652.id_data: + asn1Object = test_layer(substrate, this_layer) + substrate = getNextSubstrate[this_layer](asn1Object) + this_layer = getNextLayer[this_layer](asn1Object) + else: + asn1Object = test_layer(substrate, this_layer) + substrate = getNextSubstrate[this_layer](asn1Object) + this_layer = getNextLayer[this_layer](asn1Object) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, + asn1Spec=rfc5652.ContentInfo(), + decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual(rfc4073.id_ct_contentCollection, asn1Object['contentType']) + + for ci in asn1Object['content']: + self.assertIn(ci['contentType'], rfc5652.cmsContentTypesMap) + self.assertEqual(rfc4073.id_ct_contentWithAttrs, ci['contentType']) + + next_ci = ci['content']['content'] + + self.assertIn(next_ci['contentType'], rfc5652.cmsContentTypesMap) + self.assertEqual(rfc5652.id_data, next_ci['contentType']) + self.assertIn(str2octs('Content-Type: text'), next_ci['content']) + + for attr in ci['content']['attrs']: + self.assertIn(attr['attrType'], rfc5652.cmsAttributesMap) + if attr['attrType'] == rfc2634.id_aa_contentHint: + self.assertIn('RFC 4073', attr['attrValues'][0]['contentDescription']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc4108.py b/tests/test_rfc4108.py new file mode 100644 index 0000000..9d71601 --- /dev/null +++ b/tests/test_rfc4108.py @@ -0,0 +1,113 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc4108 + + +class CMSFirmwareWrapperTestCase(unittest.TestCase): + pem_text = """\ +MIIEvAYJKoZIhvcNAQcCoIIErTCCBKkCAQExDTALBglghkgBZQMEAgEwggIVBgsq +hkiG9w0BCRABEKCCAgQEggIA3ntqPr5kDpx+//pgWGfHCH/Ht4pbenGwXv80txyE +Y0I2mT9BUGz8ILkbhD7Xz89pBS5KhEJpthxH8WREJtvS+wL4BqYLt23wjWoZy5Gt +5dPzWgaNlV/aQ5AdfAY9ljmnNYnK8D8r8ur7bQM4cKUdxry+QA0nqXHMAOSpx4Um +8impCc0BICXaFfL3zBrNxyPubbFO9ofbYOAWaNmmIAhzthXf12vDrLostIqmYrP4 +LMRCjTr4LeYaVrAWfKtbUbByN6IuBef3Qt5cJaChr74udz3JvbYFsUvCpl64kpRq +g2CT6R+xE4trO/pViJlI15dvJVz04BBYQ2jQsutJwChi97/DDcjIv03VBmrwRE0k +RJNFP9vpDM8CxJIqcobC5Kuv8b0GqGfGl6ouuQKEVMfBcrupgjk3oc3KL1iVdSr1 ++74amb1vDtTMWNm6vWRqh+Kk17NGEi2mNvYkkZUTIHNGH7OgiDclFU8dSMZd1fun +/D9dmiFiErDB3Fzr4+8Qz0aKedNE/1uvM+dhu9qjuRdkDzZ4S7txTfk6y9pG9iyk +aEeTV2kElKXblgi+Cf0Ut4f5he8rt6jveHdMo9X36YiUQVvevj2cgN7lFivEnFYV +QY0xugpP7lvEFDfsi2+0ozgP8EKOLYaCUKpuvttlYJ+vdtUFEijizEZ4cx02RsXm +EesxggJ6MIICdgIBA4AUnutnybladNRNLxY5ZoDoAbXLpJwwCwYJYIZIAWUDBAIB +oIG8MBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABEDArBgsqhkiG9w0BCRACJDEc +MBoGCysGAQQBjb9BAQEqBgsrBgEEAY2/QQEBMDAvBgkqhkiG9w0BCQQxIgQgAJfv +uasB4P6WDLOkOyvj33YPgZW4olHbidzyh1EKP9YwQAYLKoZIhvcNAQkQAikxMTAv +MAsGCWCGSAFlAwQCAQQgAJfvuasB4P6WDLOkOyvj33YPgZW4olHbidzyh1EKP9Yw +CwYJKoZIhvcNAQELBIIBgDivAlSLbMPPu+zV+pPcYpNp+A1mwVOytjMBzSo31kR/ +qEu+hVrDknAOk9IdCaDvcz612CcfNT85/KzrYvWWxOP2woU/vZj253SnndALpfNN +n3/crJjF6hKgkjUwoXebI7kuj5WCh2q5lkd6xUa+jkCw+CINcN43thtS66UsVI4d +mv02EvsS2cxPY/508uaQZ6AYAacm667bgX8xEjbzACMOeMCuvKQXWAuh3DkNk+gV +xizHDw7xZxXgMGMAnJglAeBtd3Si5ztILw9U2gKUqFn/nOgy+eW63JuU/q31/Hgg +ZATjyBznSzneTZrw8/ePoSCj7E9vBeCTUkeFbVB2tJK1iYDMblp6HUuwgYuGKXy/ +ZwKL3GvB11qg7ntdEyjdLq0xcVrht/K0d2dPo4iO4Ac7c1xbFMDAlWOt4FMPWh6O +iTh55YvT7hAJjTbB5ebgMA9QJnAczQPFnaIePnlFrkETd3YyLK4yHwnoIGo1GiW/ +dsnhVtIdkPtfJIvcYteYJg== +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + inner, rest = der_decoder(asn1Object['content'], asn1Spec=rfc5652.SignedData()) + + self.assertEqual( + rfc4108.id_ct_firmwarePackage, inner['encapContentInfo']['eContentType']) + + self.assertTrue(inner['encapContentInfo']['eContent']) + + attribute_list = [] + + for attr in inner['signerInfos'][0]['signedAttrs']: + attribute_list.append(attr['attrType']) + if attr['attrType'] == rfc4108.id_aa_targetHardwareIDs: + av, rest = der_decoder(attr['attrValues'][0], + asn1Spec=rfc4108.TargetHardwareIdentifiers()) + self.assertEqual(2, len(av)) + + for oid in av: + self.assertIn('1.3.6.1.4.1.221121.1.1.', oid.prettyPrint()) + + self.assertIn( rfc5652.id_contentType, attribute_list) + self.assertIn( rfc5652.id_messageDigest, attribute_list) + self.assertIn(rfc4108.id_aa_targetHardwareIDs, attribute_list) + self.assertIn(rfc4108.id_aa_fwPkgMessageDigest, attribute_list) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual(asn1Object['contentType'], rfc5652.id_signedData) + + sd_eci = asn1Object['content']['encapContentInfo'] + + self.assertEqual(sd_eci['eContentType'], rfc4108.id_ct_firmwarePackage) + self.assertTrue(sd_eci['eContent'].hasValue()) + + for attr in asn1Object['content']['signerInfos'][0]['signedAttrs']: + self.assertIn(attr['attrType'], rfc5652.cmsAttributesMap) + if attr['attrType'] == rfc4108.id_aa_targetHardwareIDs: + for oid in attr['attrValues'][0]: + self.assertIn('1.3.6.1.4.1.221121.1.1.', oid.prettyPrint()) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc4210.py b/tests/test_rfc4210.py index 5c63c2e..39d407f 100644 --- a/tests/test_rfc4210.py +++ b/tests/test_rfc4210.py @@ -1,10 +1,11 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # import sys +import unittest from pyasn1.codec.der import decoder as der_decoder from pyasn1.codec.der import encoder as der_encoder @@ -12,12 +13,6 @@ from pyasn1_modules import pem from pyasn1_modules import rfc4210 -try: - import unittest2 as unittest - -except ImportError: - import unittest - class PKIMessageTestCase(unittest.TestCase): pem_text = """\ @@ -121,12 +116,13 @@ def testDerCodec(self): asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite) + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc4211.py b/tests/test_rfc4211.py new file mode 100644 index 0000000..e9be4cc --- /dev/null +++ b/tests/test_rfc4211.py @@ -0,0 +1,55 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc4211 + + +class CertificateReqTestCase(unittest.TestCase): + pem_text = """\ +MIIBozCCAZ8wggEFAgUAwTnj2jCByoABAqURMA8xDTALBgNVBAMTBHVzZXKmgZ8w +DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJ6ZQ2cYbn/lFsmBOlRltbRbFQUvvE0Q +nbopOu1kC7Bmaaz7QTx8nxeiHi4m7uxCbGGxHNoGCt7EmdG8eZUBNAcHyGlXrJdm +0z3/uNEGiBHq+xB8FnFJCA5EIJ3RWFnlbu9otSITLxWK7c5+/NHmWM+yaeHD/f/h +rp01c/8qXZfZAgMBAAGpEDAOBgNVHQ8BAf8EBAMCBeAwLzASBgkrBgEFBQcFAQEM +BTExMTExMBkGCSsGAQUFBwUBAgwMc2VydmVyX21hZ2ljoYGTMA0GCSqGSIb3DQEB +BQUAA4GBAEI3KNEvTq/n1kNVhNhPkovk1AZxyJrN1u1+7Gkc4PLjWwjLOjcEVWt4 +AajUk/gkIJ6bbeO+fZlMjHfPSDKcD6AV2hN+n72QZwfzcw3icNvBG1el9EU4XfIm +xfu5YVWi81/fw8QQ6X6YGHFQkomLd7jxakVyjxSng9BhO6GpjJNF +""" + + def setUp(self): + self.asn1Spec = rfc4211.CertReqMessages() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + count = 0 + + for crm in asn1Object: + self.assertEqual(2, crm['certReq']['certTemplate']['version']) + count += 1 + + self.assertEqual(1, count) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc4334.py b/tests/test_rfc4334.py new file mode 100644 index 0000000..9ba5fdf --- /dev/null +++ b/tests/test_rfc4334.py @@ -0,0 +1,83 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.compat.octets import str2octs + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc4334 + + +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_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + extn_list = [] + + for extn in asn1Object['tbsCertificate']['extensions']: + extn_list.append(extn['extnID']) + if extn['extnID'] in rfc5280.certificateExtensionsMap.keys(): + extnValue, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + if extn['extnID'] == rfc4334.id_pe_wlanSSID: + self.assertIn( str2octs('Example'), extnValue) + + if extn['extnID'] == rfc5280.id_ce_extKeyUsage: + self.assertIn(rfc4334.id_kp_eapOverLAN, extnValue) + self.assertIn(rfc4334.id_kp_eapOverPPP, extnValue) + + self.assertIn(rfc4334.id_pe_wlanSSID, extn_list) + self.assertIn(rfc5280.id_ce_extKeyUsage, extn_list) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc4357.py b/tests/test_rfc4357.py new file mode 100644 index 0000000..cf10d59 --- /dev/null +++ b/tests/test_rfc4357.py @@ -0,0 +1,248 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.type import univ + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc4357 + + +class SignedTestCase(unittest.TestCase): + signed_pem_text = """\ +MIIBKAYJKoZIhvcNAQcCoIIBGTCCARUCAQExDDAKBgYqhQMCAgkFADAbBgkqhkiG +9w0BBwGgDgQMc2FtcGxlIHRleHQKMYHkMIHhAgEBMIGBMG0xHzAdBgNVBAMMFkdv +c3RSMzQxMC0yMDAxIGV4YW1wbGUxEjAQBgNVBAoMCUNyeXB0b1BybzELMAkGA1UE +BhMCUlUxKTAnBgkqhkiG9w0BCQEWGkdvc3RSMzQxMC0yMDAxQGV4YW1wbGUuY29t +AhAr9cYewhG9F8fc1GJmtC4hMAoGBiqFAwICCQUAMAoGBiqFAwICEwUABEDAw0LZ +P4/+JRERiHe/icPbg0IE1iD5aCqZ9v4wO+T0yPjVtNr74caRZzQfvKZ6DRJ7/RAl +xlHbjbL0jHF+7XKp +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.signed_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + sd, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.SignedData()) + self.assertFalse(rest) + self.assertTrue(sd.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(sd)) + + encoded_null = der_encoder(univ.Null("")) + + si = sd['signerInfos'][0] + self.assertEqual(rfc4357.id_GostR3411_94, si['digestAlgorithm']['algorithm']) + self.assertEqual(encoded_null, si['digestAlgorithm']['parameters']) + + self.assertEqual(rfc4357.id_GostR3410_2001, si['signatureAlgorithm']['algorithm']) + self.assertEqual(encoded_null, si['signatureAlgorithm']['parameters']) + self.assertEqual(64, len(si['signature'])) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.signed_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + si = asn1Object['content']['signerInfos'][0] + self.assertEqual(rfc4357.id_GostR3411_94, si['digestAlgorithm']['algorithm']) + self.assertEqual(univ.Null(""), si['digestAlgorithm']['parameters']) + + self.assertEqual(rfc4357.id_GostR3410_2001, si['signatureAlgorithm']['algorithm']) + self.assertEqual(univ.Null(""), si['signatureAlgorithm']['parameters']) + + self.assertEqual(64, len(si['signature'])) + +class KeyAgreeTestCase(unittest.TestCase): + keyagree_pem_text = """\ +MIIBpAYJKoZIhvcNAQcDoIIBlTCCAZECAQIxggFQoYIBTAIBA6BloWMwHAYGKoUD +AgITMBIGByqFAwICJAAGByqFAwICHgEDQwAEQLNVOfRngZcrpcTZhB8n+4HtCDLm +mtTyAHi4/4Nk6tIdsHg8ff4DwfQG5DvMFrnF9vYZNxwXuKCqx9GhlLOlNiChCgQI +L/D20YZLMoowHgYGKoUDAgJgMBQGByqFAwICDQAwCQYHKoUDAgIfATCBszCBsDCB +gTBtMR8wHQYDVQQDDBZHb3N0UjM0MTAtMjAwMSBleGFtcGxlMRIwEAYDVQQKDAlD +cnlwdG9Qcm8xCzAJBgNVBAYTAlJVMSkwJwYJKoZIhvcNAQkBFhpHb3N0UjM0MTAt +MjAwMUBleGFtcGxlLmNvbQIQK/XGHsIRvRfH3NRiZrQuIQQqMCgEIBajHOfOTukN +8ex0aQRoHsefOu24Ox8dSn75pdnLGdXoBAST/YZ+MDgGCSqGSIb3DQEHATAdBgYq +hQMCAhUwEwQItzXhegc1oh0GByqFAwICHwGADDmxivS/qeJlJbZVyQ== +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.keyagree_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_envelopedData, asn1Object['contentType']) + + ed, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.EnvelopedData()) + self.assertFalse(rest) + self.assertTrue(ed.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(ed)) + + ri = ed['recipientInfos'][0] + alg1 = ri['kari']['originator']['originatorKey']['algorithm'] + self.assertEqual(rfc4357.id_GostR3410_2001, alg1['algorithm']) + param1, rest = der_decoder( + alg1['parameters'], + asn1Spec=rfc4357.GostR3410_2001_PublicKeyParameters()) + self.assertFalse(rest) + self.assertTrue(param1.prettyPrint()) + self.assertEqual(alg1['parameters'], der_encoder(param1)) + + self.assertEqual(rfc4357.id_GostR3410_2001_CryptoPro_XchA_ParamSet, param1['publicKeyParamSet']) + self.assertEqual(rfc4357.id_GostR3411_94_CryptoProParamSet, param1['digestParamSet']) + + self.assertEqual(8, len(ri['kari']['ukm'])) + + alg2 = ed['encryptedContentInfo']['contentEncryptionAlgorithm'] + self.assertEqual(rfc4357.id_Gost28147_89, alg2['algorithm'], ) + param2, rest = der_decoder( + alg2['parameters'], + asn1Spec=rfc4357.Gost28147_89_Parameters()) + self.assertFalse(rest) + self.assertTrue(param1.prettyPrint()) + self.assertEqual(alg2['parameters'], der_encoder(param2)) + + self.assertEqual(8, len(param2['iv'])) + self.assertEqual(rfc4357.id_Gost28147_89_CryptoPro_A_ParamSet, param2['encryptionParamSet']) + + def testOpenTypes(self): + openTypeMap = { + rfc4357.id_GostR3410_2001: rfc4357.GostR3410_2001_PublicKeyParameters(), + rfc4357.id_Gost28147_89: rfc4357.Gost28147_89_Parameters(), + } + + substrate = pem.readBase64fromText(self.keyagree_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, + openTypes=openTypeMap, decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_envelopedData, asn1Object['contentType']) + + ri = asn1Object['content']['recipientInfos'][0] + alg1 = ri['kari']['originator']['originatorKey']['algorithm'] + self.assertEqual(rfc4357.id_GostR3410_2001, alg1['algorithm']) + param1 = alg1['parameters'] + self.assertEqual(rfc4357.id_GostR3410_2001_CryptoPro_XchA_ParamSet, param1['publicKeyParamSet']) + self.assertEqual(rfc4357.id_GostR3411_94_CryptoProParamSet, param1['digestParamSet']) + + self.assertEqual(8, len(ri['kari']['ukm'])) + + alg2 = asn1Object['content']['encryptedContentInfo']['contentEncryptionAlgorithm'] + self.assertEqual(rfc4357.id_Gost28147_89, alg2['algorithm']) + param2 = alg2['parameters'] + self.assertEqual(8, len(param2['iv'])) + self.assertEqual(rfc4357.id_Gost28147_89_CryptoPro_A_ParamSet, param2['encryptionParamSet']) + + +class KeyTransportTestCase(unittest.TestCase): + keytrans_pem_text = """\ +MIIBpwYJKoZIhvcNAQcDoIIBmDCCAZQCAQAxggFTMIIBTwIBADCBgTBtMR8wHQYD +VQQDDBZHb3N0UjM0MTAtMjAwMSBleGFtcGxlMRIwEAYDVQQKDAlDcnlwdG9Qcm8x +CzAJBgNVBAYTAlJVMSkwJwYJKoZIhvcNAQkBFhpHb3N0UjM0MTAtMjAwMUBleGFt +cGxlLmNvbQIQK/XGHsIRvRfH3NRiZrQuITAcBgYqhQMCAhMwEgYHKoUDAgIkAAYH +KoUDAgIeAQSBpzCBpDAoBCBqL6ghBpVon5/kR6qey2EVK35BYLxdjfv1PSgbGJr5 +dQQENm2Yt6B4BgcqhQMCAh8BoGMwHAYGKoUDAgITMBIGByqFAwICJAAGByqFAwIC +HgEDQwAEQE0rLzOQ5tyj3VUqzd/g7/sx93N+Tv+/eImKK8PNMZQESw5gSJYf28dd +Em/askCKd7W96vLsNMsjn5uL3Z4SwPYECJeV4ywrrSsMMDgGCSqGSIb3DQEHATAd +BgYqhQMCAhUwEwQIvBCLHwv/NCkGByqFAwICHwGADKqOch3uT7Mu4w+hNw== +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.keytrans_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_envelopedData, asn1Object['contentType']) + + ed, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.EnvelopedData()) + self.assertFalse(rest) + self.assertTrue(ed.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(ed)) + + ri = ed['recipientInfos'][0] + alg1 = ri['ktri']['keyEncryptionAlgorithm'] + self.assertEqual(rfc4357.id_GostR3410_2001, alg1['algorithm']) + param1, rest = der_decoder( + alg1['parameters'], asn1Spec=rfc4357.GostR3410_2001_PublicKeyParameters()) + self.assertFalse(rest) + self.assertTrue(param1.prettyPrint()) + self.assertEqual(alg1['parameters'], der_encoder(param1)) + self.assertEqual(rfc4357.id_GostR3410_2001_CryptoPro_XchA_ParamSet, param1['publicKeyParamSet']) + self.assertEqual(rfc4357.id_GostR3411_94_CryptoProParamSet, param1['digestParamSet']) + + alg2 = ed['encryptedContentInfo']['contentEncryptionAlgorithm'] + self.assertEqual(rfc4357.id_Gost28147_89, alg2['algorithm']) + param2, rest = der_decoder( + alg2['parameters'], asn1Spec=rfc4357.Gost28147_89_Parameters()) + self.assertFalse(rest) + self.assertTrue(param2.prettyPrint()) + self.assertEqual(alg2['parameters'], der_encoder(param2)) + self.assertEqual(8, len(param2['iv'])) + self.assertEqual(rfc4357.id_Gost28147_89_CryptoPro_A_ParamSet, param2['encryptionParamSet']) + + def testOpenTypes(self): + openTypeMap = { + rfc4357.id_GostR3410_2001: rfc4357.GostR3410_2001_PublicKeyParameters(), + rfc4357.id_Gost28147_89: rfc4357.Gost28147_89_Parameters(), + } + + substrate = pem.readBase64fromText(self.keytrans_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, + openTypes=openTypeMap, decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + ri = asn1Object['content']['recipientInfos'][0] + alg1 = ri['ktri']['keyEncryptionAlgorithm'] + self.assertEqual(rfc4357.id_GostR3410_2001, alg1['algorithm']) + param1 = alg1['parameters'] + self.assertEqual(rfc4357.id_GostR3410_2001_CryptoPro_XchA_ParamSet, param1['publicKeyParamSet']) + self.assertEqual(rfc4357.id_GostR3411_94_CryptoProParamSet, param1['digestParamSet']) + + alg2 = asn1Object['content']['encryptedContentInfo']['contentEncryptionAlgorithm'] + self.assertEqual(rfc4357.id_Gost28147_89, alg2['algorithm']) + param2 = alg2['parameters'] + self.assertEqual(8, len(param2['iv'])) + self.assertEqual(rfc4357.id_Gost28147_89_CryptoPro_A_ParamSet, param2['encryptionParamSet']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc4387.py b/tests/test_rfc4387.py new file mode 100644 index 0000000..5c12225 --- /dev/null +++ b/tests/test_rfc4387.py @@ -0,0 +1,84 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc4387 + + +class CertificateTestCase(unittest.TestCase): + pem_text = """\ +MIIDLzCCArWgAwIBAgIJAKWzVCgbsG5JMAoGCCqGSM49BAMDMD8xCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9n +dXMgQ0EwHhcNMTkxMTIyMDI1MzAzWhcNMjAxMTIxMDI1MzAzWjBZMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xEDAOBgNVBAoTB0V4 +YW1wbGUxGTAXBgNVBAMTEHJlcG8uZXhhbXBsZS5jb20wdjAQBgcqhkjOPQIBBgUr +gQQAIgNiAAS/J1NNkqicN432Uwlw+Gu4pLvYpSr2W8zJvCOy61ncEzKNIs4cxqSc +N0rl6K32tNCQGCsQFaBK4wZKXbHpUEPWrfYAWYebYDOhMlOE/agxH3nZRRnYv4O7 +pGrk/YZamGijggFhMIIBXTALBgNVHQ8EBAMCB4AwQgYJYIZIAYb4QgENBDUWM1Ro +aXMgY2VydGlmaWNhdGUgY2Fubm90IGJlIHRydXN0ZWQgZm9yIGFueSBwdXJwb3Nl +LjAdBgNVHQ4EFgQUWDRoN3XtN1n8ZH+bQuSAsr42gQwwHwYDVR0jBBgwFoAU8jXb +NATapVXyvWkDmbBi7OIVCMEwgckGCCsGAQUFBwEBBIG8MIG5MCQGCCsGAQUFBzAB +hhhodHRwOi8vb2NzcC5leGFtcGxlLmNvbS8wMgYIKwYBBQUHMAKGJmh0dHA6Ly9y +ZXBvLmV4YW1wbGUuY29tL2NhaXNzdWVycy5odG1sMC4GCCsGAQUFBzAGhiJodHRw +Oi8vcmVwby5leGFtcGxlLmNvbS9jZXJ0cy5odG1sMC0GCCsGAQUFBzAHhiFodHRw +Oi8vcmVwby5leGFtcGxlLmNvbS9jcmxzLmh0bWwwCgYIKoZIzj0EAwMDaAAwZQIw +C9Y1McQ+hSEZLtzLw1xzk3QSQX6NxalySoIIoNXpcDrGZJcjLRunBg8G9B0hqG69 +AjEAxtzj8BkMvhb5d9DTKDVg5pmjl9z7UtRK87/LJM+EW/9+PAzB2IT3T+BPHKb4 +kjBJ +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + oid_list = [ + rfc4387.id_ad_http_certs, + rfc4387.id_ad_http_crls, + ] + + count = 0 + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_pe_authorityInfoAccess: + extnValue, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.AuthorityInfoAccessSyntax()) + + self.assertFalse(rest) + self.assertTrue(extnValue.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + for ad in extnValue: + if ad['accessMethod'] in oid_list: + uri = ad['accessLocation']['uniformResourceIdentifier'] + self.assertIn('http://repo.example.com/c', uri) + count += 1 + + self.assertEqual(len(oid_list), count) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + import sys + + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc4476.py b/tests/test_rfc4476.py new file mode 100644 index 0000000..b0a8fd3 --- /dev/null +++ b/tests/test_rfc4476.py @@ -0,0 +1,144 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5755 +from pyasn1_modules import rfc4476 + + +class AttributeCertificatePolicyTestCase(unittest.TestCase): + pem_text = """\ +MIID7zCCA1gCAQEwgY+gUTBKpEgwRjEjMCEGA1UEAwwaQUNNRSBJbnRlcm1lZGlh +dGUgRUNEU0EgQ0ExCzAJBgNVBAYTAkZJMRIwEAYDVQQKDAlBQ01FIEx0ZC4CAx7N +WqE6pDgwNjETMBEGA1UEAwwKQUNNRSBFQ0RTQTELMAkGA1UEBhMCRkkxEjAQBgNV +BAoMCUFDTUUgTHRkLqBWMFSkUjBQMQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkEx +EDAOBgNVBAcMB0hlcm5kb24xIjAgBgNVBAoMGUJvZ3VzIEF0dHJpYnV0ZSBBdXRo +b3RpdHkwDQYJKoZIhvcNAQELBQACBAu1MO4wIhgPMjAxOTEyMTUxMjAwMDBaGA8y +MDE5MTIzMTEyMDAwMFowgfIwPAYIKwYBBQUHCgExMDAuhgt1cm46c2VydmljZaQV +MBMxETAPBgNVBAMMCHVzZXJuYW1lBAhwYXNzd29yZDAyBggrBgEFBQcKAjEmMCSG +C3VybjpzZXJ2aWNlpBUwEzERMA8GA1UEAwwIdXNlcm5hbWUwNQYIKwYBBQUHCgMx +KTAnoBikFjAUMRIwEAYDVQQDDAlBQ01FIEx0ZC4wCwwJQUNNRSBMdGQuMCAGCCsG +AQUFBwoEMRQwEjAQDAZncm91cDEMBmdyb3VwMjAlBgNVBEgxHjANoQuGCXVybjpy +b2xlMTANoQuGCXVybjpyb2xlMjCCATkwHwYDVR0jBBgwFoAUgJCMhskAsEBzvklA +X8yJBOXO500wCQYDVR04BAIFADA8BgNVHTcENTAzoAqGCHVybjp0ZXN0oBaCFEFD +TUUtTHRkLmV4YW1wbGUuY29toA2GC3Vybjphbm90aGVyMIHMBggrBgEFBQcBDwSB +vzCBvDCBuQYKKwYBBAGBrGAwCjCBqjBFBggrBgEFBQcCBBY5aHR0cHM6Ly93d3cu +ZXhhbXBsZS5jb20vYXR0cmlidXRlLWNlcnRpZmljYXRlLXBvbGljeS5odG1sMGEG +CCsGAQUFBwIFMFUwIwwZQm9ndXMgQXR0cmlidXRlIEF1dGhvcml0eTAGAgEKAgEU +Gi5URVNUIGF0dHJpYnV0ZSBjZXJ0aWZpY2F0ZSBwb2xpY3kgZGlzcGxheSB0ZXh0 +MA0GCSqGSIb3DQEBCwUAA4GBACygfTs6TkPurZQTLufcE3B1H2707OXKsJlwRpuo +dR2oJbunSHZ94jcJHs5dfbzFs6vNfVLlBiDBRieX4p+4JcQ2P44bkgyiUTJu7g1b +6C1liB3vO6yH5hOZicOAaKd+c/myuGb9uFRoaXNfc2lnbmF0dXJlX2lzX2ludmFs +aWQh +""" + + def setUp(self): + self.asn1Spec = rfc5755.AttributeCertificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(1, asn1Object['acinfo']['version']) + + found_ac_policy_qualifier1 = False + found_ac_policy_qualifier2 = False + for extn in asn1Object['acinfo']['extensions']: + self.assertIn(extn['extnID'], rfc5280.certificateExtensionsMap) + if extn['extnID'] == rfc4476.id_pe_acPolicies: + ev, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertFalse(rest) + self.assertTrue(ev.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(ev)) + + oid = univ.ObjectIdentifier((1, 3, 6, 1, 4, 1, 22112, 48, 10,)) + self.assertEqual(oid, ev[0]['policyIdentifier']) + + for pq in ev[0]['policyQualifiers']: + self.assertIn( + pq['policyQualifierId'], rfc5280.policyQualifierInfoMap) + + pqv, rest = der_decoder( + pq['qualifier'], + asn1Spec=rfc5280.policyQualifierInfoMap[ + pq['policyQualifierId']]) + + self.assertFalse(rest) + self.assertTrue(pqv.prettyPrint()) + self.assertEqual(pq['qualifier'], der_encoder(pqv)) + + if pq['policyQualifierId'] == rfc4476.id_qt_acps: + self.assertIn('example.com', pqv) + found_ac_policy_qualifier1 = True + + if pq['policyQualifierId'] == rfc4476.id_qt_acunotice: + self.assertIn(20, pqv[0]['noticeNumbers']) + found_ac_policy_qualifier2 = True + + assert found_ac_policy_qualifier1 + assert found_ac_policy_qualifier2 + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(1, asn1Object['acinfo']['version']) + + found_ac_policy_qualifier1 = False + found_ac_policy_qualifier2 = False + for extn in asn1Object['acinfo']['extensions']: + if extn['extnID'] == rfc4476.id_pe_acPolicies: + ev, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']], + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(ev.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(ev)) + + oid = univ.ObjectIdentifier((1, 3, 6, 1, 4, 1, 22112, 48, 10,)) + self.assertEqual(oid, ev[0]['policyIdentifier']) + + for pq in ev[0]['policyQualifiers']: + + if pq['policyQualifierId'] == rfc4476.id_qt_acps: + self.assertIn('example.com', pq['qualifier']) + found_ac_policy_qualifier1 = True + + if pq['policyQualifierId'] == rfc4476.id_qt_acunotice: + self.assertIn(20, pq['qualifier'][0]['noticeNumbers']) + found_ac_policy_qualifier2 = True + + assert found_ac_policy_qualifier1 + assert found_ac_policy_qualifier2 + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc4490.py b/tests/test_rfc4490.py new file mode 100644 index 0000000..5c3b8cf --- /dev/null +++ b/tests/test_rfc4490.py @@ -0,0 +1,274 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.type import univ + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc4357 +from pyasn1_modules import rfc4490 + + +class SignedTestCase(unittest.TestCase): + signed_pem_text = """\ +MIIBKAYJKoZIhvcNAQcCoIIBGTCCARUCAQExDDAKBgYqhQMCAgkFADAbBgkqhkiG +9w0BBwGgDgQMc2FtcGxlIHRleHQKMYHkMIHhAgEBMIGBMG0xHzAdBgNVBAMMFkdv +c3RSMzQxMC0yMDAxIGV4YW1wbGUxEjAQBgNVBAoMCUNyeXB0b1BybzELMAkGA1UE +BhMCUlUxKTAnBgkqhkiG9w0BCQEWGkdvc3RSMzQxMC0yMDAxQGV4YW1wbGUuY29t +AhAr9cYewhG9F8fc1GJmtC4hMAoGBiqFAwICCQUAMAoGBiqFAwICEwUABEDAw0LZ +P4/+JRERiHe/icPbg0IE1iD5aCqZ9v4wO+T0yPjVtNr74caRZzQfvKZ6DRJ7/RAl +xlHbjbL0jHF+7XKp +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.signed_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + sd, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.SignedData()) + self.assertFalse(rest) + self.assertTrue(sd.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(sd)) + + encoded_null = der_encoder(univ.Null("")) + + si = sd['signerInfos'][0] + self.assertEqual(rfc4357.id_GostR3411_94, si['digestAlgorithm']['algorithm']) + self.assertEqual(encoded_null, si['digestAlgorithm']['parameters']) + + self.assertEqual(rfc4357.id_GostR3410_2001, si['signatureAlgorithm']['algorithm']) + self.assertEqual(encoded_null, si['signatureAlgorithm']['parameters']) + + sig = rfc4490.GostR3410_2001_Signature() + sig = si['signature'] + self.assertEqual(64, len(sig)) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.signed_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + si = asn1Object['content']['signerInfos'][0] + self.assertEqual(rfc4357.id_GostR3411_94, si['digestAlgorithm']['algorithm']) + self.assertEqual(univ.Null(""), si['digestAlgorithm']['parameters']) + + self.assertEqual(rfc4357.id_GostR3410_2001, si['signatureAlgorithm']['algorithm']) + self.assertEqual(univ.Null(""), si['signatureAlgorithm']['parameters']) + + sig = rfc4490.GostR3410_2001_Signature() + sig = si['signature'] + self.assertEqual(64, len(sig)) + +class KeyAgreeTestCase(unittest.TestCase): + keyagree_pem_text = """\ +MIIBpAYJKoZIhvcNAQcDoIIBlTCCAZECAQIxggFQoYIBTAIBA6BloWMwHAYGKoUD +AgITMBIGByqFAwICJAAGByqFAwICHgEDQwAEQLNVOfRngZcrpcTZhB8n+4HtCDLm +mtTyAHi4/4Nk6tIdsHg8ff4DwfQG5DvMFrnF9vYZNxwXuKCqx9GhlLOlNiChCgQI +L/D20YZLMoowHgYGKoUDAgJgMBQGByqFAwICDQAwCQYHKoUDAgIfATCBszCBsDCB +gTBtMR8wHQYDVQQDDBZHb3N0UjM0MTAtMjAwMSBleGFtcGxlMRIwEAYDVQQKDAlD +cnlwdG9Qcm8xCzAJBgNVBAYTAlJVMSkwJwYJKoZIhvcNAQkBFhpHb3N0UjM0MTAt +MjAwMUBleGFtcGxlLmNvbQIQK/XGHsIRvRfH3NRiZrQuIQQqMCgEIBajHOfOTukN +8ex0aQRoHsefOu24Ox8dSn75pdnLGdXoBAST/YZ+MDgGCSqGSIb3DQEHATAdBgYq +hQMCAhUwEwQItzXhegc1oh0GByqFAwICHwGADDmxivS/qeJlJbZVyQ== +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.keyagree_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_envelopedData, asn1Object['contentType']) + + ed, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.EnvelopedData()) + self.assertFalse(rest) + self.assertTrue(ed.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(ed)) + + ri = ed['recipientInfos'][0] + alg1 = ri['kari']['originator']['originatorKey']['algorithm'] + self.assertEqual(rfc4357.id_GostR3410_2001, alg1['algorithm']) + param1, rest = der_decoder( + alg1['parameters'], + asn1Spec=rfc4357.GostR3410_2001_PublicKeyParameters()) + self.assertFalse(rest) + self.assertTrue(param1.prettyPrint()) + self.assertEqual(alg1['parameters'], der_encoder(param1)) + + self.assertEqual(rfc4357.id_GostR3410_2001_CryptoPro_XchA_ParamSet, param1['publicKeyParamSet']) + self.assertEqual(rfc4357.id_GostR3411_94_CryptoProParamSet, param1['digestParamSet']) + + self.assertEqual(8, len(ri['kari']['ukm'])) + + alg2 = ri['kari']['keyEncryptionAlgorithm'] + self.assertEqual(rfc4490.id_GostR3410_2001_CryptoPro_ESDH, alg2['algorithm']) + param2, rest = der_decoder( + alg2['parameters'], asn1Spec=rfc4357.AlgorithmIdentifier()) + self.assertFalse(rest) + self.assertTrue(param2.prettyPrint()) + self.assertEqual(alg2['parameters'], der_encoder(param2)) + + self.assertEqual(rfc4490.id_Gost28147_89_None_KeyWrap, param2['algorithm']) + kwa_p, rest = der_decoder( + param2['parameters'], asn1Spec=rfc4490.Gost28147_89_KeyWrapParameters()) + self.assertFalse(rest) + self.assertTrue(kwa_p.prettyPrint()) + self.assertEqual(param2['parameters'], der_encoder(kwa_p)) + self.assertEqual(rfc4357.id_Gost28147_89_CryptoPro_A_ParamSet, kwa_p['encryptionParamSet']) + + alg3 = ed['encryptedContentInfo']['contentEncryptionAlgorithm'] + self.assertEqual(rfc4357.id_Gost28147_89, alg3['algorithm']) + param3, rest = der_decoder(alg3['parameters'], asn1Spec=rfc4357.Gost28147_89_Parameters()) + self.assertFalse(rest) + self.assertTrue(param3.prettyPrint()) + self.assertEqual(alg3['parameters'], der_encoder(param3)) + self.assertEqual(8, len(param3['iv'])) + self.assertEqual(rfc4357.id_Gost28147_89_CryptoPro_A_ParamSet, param3['encryptionParamSet']) + + def testOpenTypes(self): + openTypeMap = { + rfc4357.id_GostR3410_2001: rfc4357.GostR3410_2001_PublicKeyParameters(), + rfc4357.id_Gost28147_89: rfc4357.Gost28147_89_Parameters(), + rfc4490.id_GostR3410_2001_CryptoPro_ESDH: rfc5280.AlgorithmIdentifier(), + } + + substrate = pem.readBase64fromText(self.keyagree_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, + openTypes=openTypeMap, decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_envelopedData, asn1Object['contentType']) + + ri = asn1Object['content']['recipientInfos'][0] + alg1 = ri['kari']['originator']['originatorKey']['algorithm'] + self.assertEqual(rfc4357.id_GostR3410_2001, alg1['algorithm']) + param1 = alg1['parameters'] + self.assertEqual(rfc4357.id_GostR3410_2001_CryptoPro_XchA_ParamSet, param1['publicKeyParamSet']) + self.assertEqual(rfc4357.id_GostR3411_94_CryptoProParamSet, param1['digestParamSet']) + + self.assertEqual(8, len(ri['kari']['ukm'])) + + alg2 = ri['kari']['keyEncryptionAlgorithm'] + self.assertEqual(rfc4490.id_GostR3410_2001_CryptoPro_ESDH, alg2['algorithm']) + param2 = alg2['parameters'] + self.assertEqual(rfc4490.id_Gost28147_89_None_KeyWrap, param2['algorithm']) + kwa_p = param2['parameters'] + self.assertEqual(rfc4357.id_Gost28147_89_CryptoPro_A_ParamSet, kwa_p['encryptionParamSet']) + + alg3 = asn1Object['content']['encryptedContentInfo']['contentEncryptionAlgorithm'] + self.assertEqual(rfc4357.id_Gost28147_89, alg3['algorithm']) + param3 = alg3['parameters'] + self.assertEqual(8, len(param3['iv'])) + self.assertEqual(rfc4357.id_Gost28147_89_CryptoPro_A_ParamSet, param3['encryptionParamSet']) + +class KeyTransportTestCase(unittest.TestCase): + keytrans_pem_text = """\ +MIIBpwYJKoZIhvcNAQcDoIIBmDCCAZQCAQAxggFTMIIBTwIBADCBgTBtMR8wHQYD +VQQDDBZHb3N0UjM0MTAtMjAwMSBleGFtcGxlMRIwEAYDVQQKDAlDcnlwdG9Qcm8x +CzAJBgNVBAYTAlJVMSkwJwYJKoZIhvcNAQkBFhpHb3N0UjM0MTAtMjAwMUBleGFt +cGxlLmNvbQIQK/XGHsIRvRfH3NRiZrQuITAcBgYqhQMCAhMwEgYHKoUDAgIkAAYH +KoUDAgIeAQSBpzCBpDAoBCBqL6ghBpVon5/kR6qey2EVK35BYLxdjfv1PSgbGJr5 +dQQENm2Yt6B4BgcqhQMCAh8BoGMwHAYGKoUDAgITMBIGByqFAwICJAAGByqFAwIC +HgEDQwAEQE0rLzOQ5tyj3VUqzd/g7/sx93N+Tv+/eImKK8PNMZQESw5gSJYf28dd +Em/askCKd7W96vLsNMsjn5uL3Z4SwPYECJeV4ywrrSsMMDgGCSqGSIb3DQEHATAd +BgYqhQMCAhUwEwQIvBCLHwv/NCkGByqFAwICHwGADKqOch3uT7Mu4w+hNw== +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.keytrans_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_envelopedData, asn1Object['contentType']) + + ed, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.EnvelopedData()) + self.assertFalse(rest) + self.assertTrue(ed.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(ed)) + + ri = ed['recipientInfos'][0] + alg1 = ri['ktri']['keyEncryptionAlgorithm'] + self.assertEqual(rfc4357.id_GostR3410_2001, alg1['algorithm']) + param1, rest = der_decoder( + alg1['parameters'], asn1Spec=rfc4357.GostR3410_2001_PublicKeyParameters()) + self.assertFalse(rest) + self.assertTrue(param1.prettyPrint()) + self.assertEqual(alg1['parameters'], der_encoder(param1)) + self.assertEqual(rfc4357.id_GostR3410_2001_CryptoPro_XchA_ParamSet, param1['publicKeyParamSet']) + self.assertEqual(rfc4357.id_GostR3411_94_CryptoProParamSet, param1['digestParamSet']) + + alg2 = ed['encryptedContentInfo']['contentEncryptionAlgorithm'] + self.assertEqual(rfc4357.id_Gost28147_89, alg2['algorithm']) + param2, rest = der_decoder( + alg2['parameters'], asn1Spec=rfc4357.Gost28147_89_Parameters()) + self.assertFalse(rest) + self.assertTrue(param2.prettyPrint()) + self.assertEqual(alg2['parameters'], der_encoder(param2)) + self.assertEqual(8, len(param2['iv'])) + self.assertEqual(rfc4357.id_Gost28147_89_CryptoPro_A_ParamSet, param2['encryptionParamSet']) + + def testOpenTypes(self): + openTypeMap = { + rfc4357.id_GostR3410_2001: rfc4357.GostR3410_2001_PublicKeyParameters(), + rfc4357.id_Gost28147_89: rfc4357.Gost28147_89_Parameters(), + } + + substrate = pem.readBase64fromText(self.keytrans_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, + openTypes=openTypeMap, decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + ri = asn1Object['content']['recipientInfos'][0] + alg1 = ri['ktri']['keyEncryptionAlgorithm'] + self.assertEqual(rfc4357.id_GostR3410_2001, alg1['algorithm']) + param1 = alg1['parameters'] + self.assertEqual(rfc4357.id_GostR3410_2001_CryptoPro_XchA_ParamSet, param1['publicKeyParamSet']) + self.assertEqual(rfc4357.id_GostR3411_94_CryptoProParamSet, param1['digestParamSet']) + + alg2 = asn1Object['content']['encryptedContentInfo']['contentEncryptionAlgorithm'] + self.assertEqual(rfc4357.id_Gost28147_89, alg2['algorithm']) + param2 = alg2['parameters'] + self.assertEqual(8, len(param2['iv'])) + self.assertEqual(rfc4357.id_Gost28147_89_CryptoPro_A_ParamSet, param2['encryptionParamSet']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc4491.py b/tests/test_rfc4491.py new file mode 100644 index 0000000..24b94a9 --- /dev/null +++ b/tests/test_rfc4491.py @@ -0,0 +1,156 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc4491 +from pyasn1_modules import rfc4357 + + +class GostR341094CertificateTestCase(unittest.TestCase): + gostR3410_94_cert_pem_text = """\ +MIICCzCCAboCECMO42BGlSTOxwvklBgufuswCAYGKoUDAgIEMGkxHTAbBgNVBAMM +FEdvc3RSMzQxMC05NCBleGFtcGxlMRIwEAYDVQQKDAlDcnlwdG9Qcm8xCzAJBgNV +BAYTAlJVMScwJQYJKoZIhvcNAQkBFhhHb3N0UjM0MTAtOTRAZXhhbXBsZS5jb20w +HhcNMDUwODE2MTIzMjUwWhcNMTUwODE2MTIzMjUwWjBpMR0wGwYDVQQDDBRHb3N0 +UjM0MTAtOTQgZXhhbXBsZTESMBAGA1UECgwJQ3J5cHRvUHJvMQswCQYDVQQGEwJS +VTEnMCUGCSqGSIb3DQEJARYYR29zdFIzNDEwLTk0QGV4YW1wbGUuY29tMIGlMBwG +BiqFAwICFDASBgcqhQMCAiACBgcqhQMCAh4BA4GEAASBgLuEZuF5nls02CyAfxOo +GWZxV/6MVCUhR28wCyd3RpjG+0dVvrey85NsObVCNyaE4g0QiiQOHwxCTSs7ESuo +v2Y5MlyUi8Go/htjEvYJJYfMdRv05YmKCYJo01x3pg+2kBATjeM+fJyR1qwNCCw+ +eMG1wra3Gqgqi0WBkzIydvp7MAgGBiqFAwICBANBABHHCH4S3ALxAiMpR3aPRyqB +g1DjB8zy5DEjiULIc+HeIveF81W9lOxGkZxnrFjXBSqnjLeFKgF1hffXOAP7zUM= +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.gostR3410_94_cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + sa1 = asn1Object['signatureAlgorithm']['algorithm'] + self.assertEqual(rfc4491.id_GostR3411_94_with_GostR3410_94, sa1) + + sa2 = asn1Object['tbsCertificate']['signature']['algorithm'] + self.assertEqual(rfc4491.id_GostR3411_94_with_GostR3410_94, sa2) + + spki_a = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + self.assertEqual(rfc4491.id_GostR3410_94, spki_a['algorithm']) + + pk_p, rest = der_decoder( + spki_a['parameters'], + asn1Spec=rfc4491.GostR3410_94_PublicKeyParameters()) + + self.assertFalse(rest) + self.assertTrue(pk_p.prettyPrint()) + self.assertEqual(spki_a['parameters'], der_encoder(pk_p)) + self.assertEqual(rfc4357.id_GostR3411_94_CryptoProParamSet, pk_p['digestParamSet']) + + def testOpenTypes(self): + openTypesMap = { + rfc4491.id_GostR3410_94: rfc4491.GostR3410_94_PublicKeyParameters(), + } + + substrate = pem.readBase64fromText(self.gostR3410_94_cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, + openTypes=openTypesMap, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + sa1 = asn1Object['signatureAlgorithm']['algorithm'] + self.assertEqual(rfc4491.id_GostR3411_94_with_GostR3410_94, sa1) + + sa2 = asn1Object['tbsCertificate']['signature']['algorithm'] + self.assertEqual(rfc4491.id_GostR3411_94_with_GostR3410_94, sa2) + + spki_a = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + self.assertEqual(rfc4491.id_GostR3410_94, spki_a['algorithm']) + self.assertEqual(rfc4357.id_GostR3411_94_CryptoProParamSet, spki_a['parameters']['digestParamSet']) + +class GostR34102001CertificateTestCase(unittest.TestCase): + gostR3410_2001_cert_pem_text = """\ +MIIB0DCCAX8CECv1xh7CEb0Xx9zUYma0LiEwCAYGKoUDAgIDMG0xHzAdBgNVBAMM +Fkdvc3RSMzQxMC0yMDAxIGV4YW1wbGUxEjAQBgNVBAoMCUNyeXB0b1BybzELMAkG +A1UEBhMCUlUxKTAnBgkqhkiG9w0BCQEWGkdvc3RSMzQxMC0yMDAxQGV4YW1wbGUu +Y29tMB4XDTA1MDgxNjE0MTgyMFoXDTE1MDgxNjE0MTgyMFowbTEfMB0GA1UEAwwW +R29zdFIzNDEwLTIwMDEgZXhhbXBsZTESMBAGA1UECgwJQ3J5cHRvUHJvMQswCQYD +VQQGEwJSVTEpMCcGCSqGSIb3DQEJARYaR29zdFIzNDEwLTIwMDFAZXhhbXBsZS5j +b20wYzAcBgYqhQMCAhMwEgYHKoUDAgIkAAYHKoUDAgIeAQNDAARAhJVodWACGkB1 +CM0TjDGJLP3lBQN6Q1z0bSsP508yfleP68wWuZWIA9CafIWuD+SN6qa7flbHy7Df +D2a8yuoaYDAIBgYqhQMCAgMDQQA8L8kJRLcnqeyn1en7U23Sw6pkfEQu3u0xFkVP +vFQ/3cHeF26NG+xxtZPz3TaTVXdoiYkXYiD02rEx1bUcM97i +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.gostR3410_2001_cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + sa1 = asn1Object['signatureAlgorithm']['algorithm'] + self.assertEqual(rfc4491.id_GostR3411_94_with_GostR3410_2001, sa1) + + sa2 = asn1Object['tbsCertificate']['signature']['algorithm'] + self.assertEqual(rfc4491.id_GostR3411_94_with_GostR3410_2001, sa2) + + spki_a = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + self.assertEqual(rfc4491.id_GostR3410_2001, spki_a['algorithm']) + + pk_p, rest = der_decoder( + spki_a['parameters'], asn1Spec=rfc4491.GostR3410_2001_PublicKeyParameters()) + + self.assertFalse(rest) + self.assertTrue(pk_p.prettyPrint()) + self.assertEqual(spki_a['parameters'], der_encoder(pk_p)) + self.assertEqual(rfc4357.id_GostR3411_94_CryptoProParamSet, pk_p['digestParamSet']) + + def testOpenTypes(self): + openTypeMap = { + rfc4491.id_GostR3410_2001: rfc4491.GostR3410_2001_PublicKeyParameters(), + } + + substrate = pem.readBase64fromText(self.gostR3410_2001_cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, + openTypes=openTypeMap, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + sa1 = asn1Object['signatureAlgorithm']['algorithm'] + self.assertEqual(rfc4491.id_GostR3411_94_with_GostR3410_2001, sa1) + + sa2 = asn1Object['tbsCertificate']['signature']['algorithm'] + self.assertEqual(rfc4491.id_GostR3411_94_with_GostR3410_2001, sa2) + + spki_a = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + self.assertEqual(rfc4491.id_GostR3410_2001, spki_a['algorithm']) + self.assertEqual(rfc4357.id_GostR3411_94_CryptoProParamSet, spki_a['parameters']['digestParamSet']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc4683.py b/tests/test_rfc4683.py new file mode 100644 index 0000000..7935ad8 --- /dev/null +++ b/tests/test_rfc4683.py @@ -0,0 +1,122 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc4683 + + +class SIMCertificateTestCase(unittest.TestCase): + cert_pem_text = """\ +MIIDOzCCAsCgAwIBAgIJAKWzVCgbsG5KMAoGCCqGSM49BAMDMD8xCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9n +dXMgQ0EwHhcNMTkxMjExMjIzODUwWhcNMjAxMjEwMjIzODUwWjBOMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xEDAOBgNVBAoTB0V4 +YW1wbGUxDjAMBgNVBAMTBUhlbnJ5MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEZj80 +YyLeDb0arJY8ZxBUMMxPEMT9+5WFVBCC1dPpUn25MmEpb82Dz1inv3xmG6sFKIHj +achlvkNGDXTUzZ1DdCF0O7gU5Z+YctwczGQVSt/2Ox0NWTiHLDpbpyoTyK0Bo4IB +dzCCAXMwHQYDVR0OBBYEFOjxtcL2ucMoTjS5MNKKpdKzXtz/MG8GA1UdIwRoMGaA +FPI12zQE2qVV8r1pA5mwYuziFQjBoUOkQTA/MQswCQYDVQQGEwJVUzELMAkGA1UE +CAwCVkExEDAOBgNVBAcMB0hlcm5kb24xETAPBgNVBAoMCEJvZ3VzIENBggkA6JHW +BpFPzvIwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAYYwQgYJYIZIAYb4QgEN +BDUWM1RoaXMgY2VydGlmaWNhdGUgY2Fubm90IGJlIHRydXN0ZWQgZm9yIGFueSBw +dXJwb3NlLjB/BgNVHREEeDB2oGEGCCsGAQUFBwgGoFUwUzANBglghkgBZQMEAgEF +AAQgnrmI6yL2lM5kmfLVn28A8PVIVgE2S7HEFtfLExhg7HsEIOaAn/Pq8hb4qn/K +imN3uyZrjAv3Uspg0VYEcetJdHSCgRFoZW5yeUBleGFtcGxlLmNvbTAKBggqhkjO +PQQDAwNpADBmAjEAiWhD493OGnqfdit6SRdBjn3N6HVaMxyVO0Lfosjf9+9FDWad +rYt3o64YQqGz9NTMAjEAmahE0EMiu/TyzRDidlG2SxmY2aHg9hQO0t38i1jInJyi +9LjB81zHEL6noTgBZsan +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + found_PEPSI = False + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectAltName: + extnValue, rest = der_decoder( + extn['extnValue'], asn1Spec=rfc5280.SubjectAltName()) + + self.assertFalse(rest) + self.assertTrue(extnValue.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + for gn in extnValue: + if gn['otherName'].hasValue(): + gn_on = gn['otherName'] + if gn_on['type-id'] == rfc4683.id_on_SIM: + self.assertIn( + gn_on['type-id'], rfc5280.anotherNameMap) + + spec = rfc5280.anotherNameMap[gn_on['type-id']] + + on, rest = der_decoder( + gn_on['value'], asn1Spec=spec) + + self.assertFalse(rest) + self.assertTrue(on.prettyPrint()) + self.assertEqual(gn_on['value'], der_encoder(on)) + + self.assertEqual( + 'e6809ff3ea', on['pEPSI'].prettyPrint()[2:12]) + + found_PEPSI = True + + self.assertTrue(found_PEPSI) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + found_PEPSI = False + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectAltName: + extnValue, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.SubjectAltName(), + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(extnValue.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + for gn in extnValue: + if gn['otherName'].hasValue(): + pepsi = gn['otherName']['value']['pEPSI'] + self.assertEqual( + 'e6809ff3ea', pepsi.prettyPrint()[2:12]) + + found_PEPSI = True + + self.assertTrue(found_PEPSI) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc4985.py b/tests/test_rfc4985.py new file mode 100644 index 0000000..b261ef9 --- /dev/null +++ b/tests/test_rfc4985.py @@ -0,0 +1,113 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc4985 + + +class XMPPCertificateTestCase(unittest.TestCase): + xmpp_server_cert_pem_text = """\ +MIIC6DCCAm+gAwIBAgIJAKWzVCgbsG5DMAoGCCqGSM49BAMDMD8xCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9n +dXMgQ0EwHhcNMTkxMDI0MjMxNjA0WhcNMjAxMDIzMjMxNjA0WjBNMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xHzAdBgNVBAoTFkV4 +YW1wbGUgUHJvZHVjdHMsIEluYy4wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQZzQlk +03nJRPF6+w1NxFELmQ5vJTjTRz3eu03CRtahK4Wnwd4GwbDe8NVHAEG2qTzBXFDu +p6RZugsBdf9GcEZHG42rThYYOzIYzVFnI7tQgA+nTWSWZN6eoU/EXcknhgijggEn +MIIBIzAdBgNVHQ4EFgQUkQpUMYcbUesEn5buI03POFnktJgwHwYDVR0jBBgwFoAU +8jXbNATapVXyvWkDmbBi7OIVCMEwCwYDVR0PBAQDAgeAMIGPBgNVHREEgYcwgYSg +KQYIKwYBBQUHCAegHRYbX3htcHAtY2xpZW50LmltLmV4YW1wbGUuY29toCkGCCsG +AQUFBwgHoB0WG194bXBwLXNlcnZlci5pbS5leGFtcGxlLmNvbaAcBggrBgEFBQcI +BaAQDA5pbS5leGFtcGxlLmNvbYIOaW0uZXhhbXBsZS5jb20wQgYJYIZIAYb4QgEN +BDUWM1RoaXMgY2VydGlmaWNhdGUgY2Fubm90IGJlIHRydXN0ZWQgZm9yIGFueSBw +dXJwb3NlLjAKBggqhkjOPQQDAwNnADBkAjAEo4mhDGC6/R39HyNgzLseNAp36qBH +yQJ/AWsBojN0av8akeVv9IuM45yqLKdiCzcCMDCjh1lFnCvurahwp5D1j9pAZMsg +nOzhcMpnHs2U/eN0lHl/JNgnbftl6Dvnt59xdA== +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.xmpp_server_cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + count = 0 + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectAltName: + extnValue, rest = der_decoder( + extn['extnValue'], asn1Spec=rfc5280.SubjectAltName()) + + self.assertFalse(rest) + self.assertTrue(extnValue.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + for gn in extnValue: + if gn['otherName'].hasValue(): + gn_on = gn['otherName'] + if gn_on['type-id'] == rfc4985.id_on_dnsSRV: + self.assertIn(gn_on['type-id'], rfc5280.anotherNameMap) + + spec = rfc5280.anotherNameMap[gn['otherName']['type-id']] + on, rest = der_decoder(gn_on['value'], asn1Spec=spec) + + self.assertFalse(rest) + self.assertTrue(on.prettyPrint()) + self.assertEqual(gn_on['value'], der_encoder(on)) + self.assertIn('im.example.com', on) + + count += 1 + + self.assertEqual(2, count) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.xmpp_server_cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + count = 0 + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectAltName: + extnValue, rest = der_decoder( + extn['extnValue'], asn1Spec=rfc5280.SubjectAltName(), + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(extnValue.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + for gn in extnValue: + if gn['otherName'].hasValue(): + if gn['otherName']['type-id'] == rfc4985.id_on_dnsSRV: + self.assertIn('im.example.com', gn['otherName']['value']) + count += 1 + + self.assertEqual(2, count) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5035.py b/tests/test_rfc5035.py new file mode 100644 index 0000000..196a6e4 --- /dev/null +++ b/tests/test_rfc5035.py @@ -0,0 +1,192 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5035 + + +class SignedMessageTestCase(unittest.TestCase): + signed_message_pem_text = """\ +MIIFzAYJKoZIhvcNAQcCoIIFvTCCBbkCAQExDTALBglghkgBZQMEAgIwUQYJKoZI +hvcNAQcBoEQEQkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbg0KDQpXYXRzb24sIGNv +bWUgaGVyZSAtIEkgd2FudCB0byBzZWUgeW91LqCCAnwwggJ4MIIB/qADAgECAgkA +pbNUKBuwbjswCgYIKoZIzj0EAwMwPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZB +MRAwDgYDVQQHDAdIZXJuZG9uMREwDwYDVQQKDAhCb2d1cyBDQTAeFw0xOTA1Mjkx +NDQ1NDFaFw0yMDA1MjgxNDQ1NDFaMHAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJW +QTEQMA4GA1UEBxMHSGVybmRvbjEQMA4GA1UEChMHRXhhbXBsZTEOMAwGA1UEAxMF +QWxpY2UxIDAeBgkqhkiG9w0BCQEWEWFsaWNlQGV4YW1wbGUuY29tMHYwEAYHKoZI +zj0CAQYFK4EEACIDYgAE+M2fBy/sRA6V1pKFqecRTE8+LuAHtZxes1wmJZrBBg+b +z7uYZfYQxI3dVB0YCSD6Mt3yXFlnmfBRwoqyArbjIBYrDbHBv2k8Csg2DhQ7qs/w +to8hMKoFgkcscqIbiV7Zo4GUMIGRMAsGA1UdDwQEAwIHgDBCBglghkgBhvhCAQ0E +NRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUgdHJ1c3RlZCBmb3IgYW55IHB1 +cnBvc2UuMB0GA1UdDgQWBBTEuloOPnrjPIGw9AKqaLsW4JYONTAfBgNVHSMEGDAW +gBTyNds0BNqlVfK9aQOZsGLs4hUIwTAKBggqhkjOPQQDAwNoADBlAjBjuR/RNbgL +3kRhmn+PJTeKaL9sh/oQgHOYTgLmSnv3+NDCkhfKuMNoo/tHrkmihYgCMQC94Mae +rDIrQpi0IDh+v0QSAv9rMife8tClafXWtDwwL8MS7oAh0ymT446Uizxx3PUxggLQ +MIICzAIBATBMMD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwH +SGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0ECCQCls1QoG7BuOzALBglghkgBZQME +AgKgggH1MBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8X +DTE5MDUyOTE4MjMxOVowJQYLKoZIhvcNAQkQAgcxFgQUAbWZQYhLO5wtUgsOCGtT +4V3aNhUwLwYLKoZIhvcNAQkQAgQxIDAeDBFXYXRzb24sIGNvbWUgaGVyZQYJKoZI +hvcNAQcBMDUGCyqGSIb3DQEJEAICMSYxJAIBAQYKKwYBBAGBrGABARMTQm9hZ3Vz +IFByaXZhY3kgTWFyazA/BgkqhkiG9w0BCQQxMgQwtuQipP2CZx7U96rGbUT06LC5 +jVFYccZW5/CaNvpcrOPiChDm2vI3m4k300z5mSZsME0GCyqGSIb3DQEJEAIBMT4w +PAQgx08hD2QnVwj1DoeRELNtdZ0PffW4BQIvcwwVc/goU6OAAQEwFTATgRFhbGlj +ZUBleGFtcGxlLmNvbTCBmwYLKoZIhvcNAQkQAi8xgYswgYgwdjB0BCACcp04gyM2 +dTDg+0ydCwlucr6Mg8Wd3J3c9V+iLHsnZzBQMEOkQTA/MQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCVkExEDAOBgNVBAcMB0hlcm5kb24xETAPBgNVBAoMCEJvZ3VzIENB +AgkApbNUKBuwbjswDjAMBgorBgEEAYGsYAEBMAoGCCqGSM49BAMDBGcwZQIxAO3K +D9YjFTKE3p383VVw/ol79WTVoMea4H1+7xn+3E1XO4oyb7qwQz0KmsGfdqWptgIw +T9yMtRLN5ZDU14y+Phzq9NKpSw/x5KyXoUKjCMc3Ru6dIW+CgcRQees+dhnvuD5U +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.signed_message_pem_text) + asn1Object, rest = der_decoder (substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + sd, rest = der_decoder(asn1Object['content'], asn1Spec=rfc5652.SignedData()) + + self.assertFalse(rest) + self.assertTrue(sd.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(sd)) + + for sa in sd['signerInfos'][0]['signedAttrs']: + sat = sa['attrType'] + sav0 = sa['attrValues'][0] + + if sat in rfc5652.cmsAttributesMap.keys(): + sav, rest = der_decoder(sav0, asn1Spec=rfc5652.cmsAttributesMap[sat]) + self.assertFalse(rest) + self.assertTrue(sav.prettyPrint()) + self.assertEqual(sav0, der_encoder(sav)) + + +class SignedReceiptTestCase(unittest.TestCase): + signed_receipt_pem_text = """\ +MIIE3gYJKoZIhvcNAQcCoIIEzzCCBMsCAQMxDTALBglghkgBZQMEAgEwga4GCyqGSIb3DQEJ +EAEBoIGeBIGbMIGYAgEBBgkqhkiG9w0BBwEEIMdPIQ9kJ1cI9Q6HkRCzbXWdD331uAUCL3MM +FXP4KFOjBGYwZAIwOLV5WCbYjy5HLHE69IqXQQHVDJQzmo18WwkFrEYH3EMsvpXEIGqsFTFN +6NV4VBe9AjA5fGOCP5IhI32YqmGfs+zDlqZyb2xSX6Gr/IfCIm0angfOI39g7lAZDyivjh5H +/oSgggJ3MIICczCCAfqgAwIBAgIJAKWzVCgbsG48MAoGCCqGSM49BAMDMD8xCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0Ew +HhcNMTkwNTI5MTkyMDEzWhcNMjAwNTI4MTkyMDEzWjBsMQswCQYDVQQGEwJVUzELMAkGA1UE +CBMCVkExEDAOBgNVBAcTB0hlcm5kb24xEDAOBgNVBAoTB0V4YW1wbGUxDDAKBgNVBAMTA0Jv +YjEeMBwGCSqGSIb3DQEJARYPYm9iQGV4YW1wbGUuY29tMHYwEAYHKoZIzj0CAQYFK4EEACID +YgAEMaRiVS8WvN8Ycmpfq75jBbOMUukNfXAg6AL0JJBXtIFAuIJcZVlkLn/xbywkcMLHK/O+ +w9RWUQa2Cjw+h8b/1Cl+gIpqLtE558bD5PfM2aYpJ/YE6yZ9nBfTQs7z1TH5o4GUMIGRMAsG +A1UdDwQEAwIHgDBCBglghkgBhvhCAQ0ENRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUg +dHJ1c3RlZCBmb3IgYW55IHB1cnBvc2UuMB0GA1UdDgQWBBTKa2Zy3iybV3+YjuLDKtNmjsIa +pTAfBgNVHSMEGDAWgBTyNds0BNqlVfK9aQOZsGLs4hUIwTAKBggqhkjOPQQDAwNnADBkAjAV +boS6OfEYQomLDi2RUkd71hzwwiQZztbxNbosahIzjR8ZQaHhjdjJlrP/T6aXBwsCMDfRweYz +3Ce4E4wPfoqQnvqpM7ZlfhstjQQGOsWAtIIfqW/l+TgCO8ux3XLV6fj36zGCAYkwggGFAgEB +MEwwPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMRAwDgYDVQQHDAdIZXJuZG9uMREwDwYD +VQQKDAhCb2d1cyBDQQIJAKWzVCgbsG48MAsGCWCGSAFlAwQCAaCBrjAaBgkqhkiG9w0BCQMx +DQYLKoZIhvcNAQkQAQEwHAYJKoZIhvcNAQkFMQ8XDTE5MDUyOTE5MzU1NVowLwYJKoZIhvcN +AQkEMSIEIGb9Hm2kCnM0CYNpZU4Uj7dN0AzOieIn9sDqZMcIcZrEMEEGCyqGSIb3DQEJEAIF +MTIEMBZzeHVja7fQ62ywyh8rtKzBP1WJooMdZ+8c6pRqfIESYIU5bQnH99OPA51QCwdOdjAK +BggqhkjOPQQDAgRoMGYCMQDZiT22xgab6RFMAPvN4fhWwzx017EzttD4VaYrpbolropBdPJ6 +jIXiZQgCwxbGTCwCMQClaQ9K+L5LTeuW50ZKSIbmBZQ5dxjtnK3OlS7hYRi6U0JKZmWbbuS8 +vFIgX7eIkd8= +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.signed_receipt_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + sd, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.SignedData()) + + self.assertFalse(rest) + self.assertTrue(sd.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(sd)) + self.assertEqual( + rfc5035.id_ct_receipt, sd['encapContentInfo']['eContentType']) + + receipt, rest = der_decoder( + sd['encapContentInfo']['eContent'], asn1Spec=rfc5035.Receipt()) + + self.assertFalse(rest) + self.assertTrue(receipt.prettyPrint()) + self.assertEqual( + sd['encapContentInfo']['eContent'], der_encoder(receipt)) + + for sa in sd['signerInfos'][0]['signedAttrs']: + sat = sa['attrType'] + sav0 = sa['attrValues'][0] + + if sat in rfc5652.cmsAttributesMap.keys(): + sav, rest = der_decoder( + sav0, asn1Spec=rfc5652.cmsAttributesMap[sat]) + self.assertFalse(rest) + self.assertTrue(sav.prettyPrint()) + self.assertEqual(sav0, der_encoder(sav)) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.signed_receipt_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertIn(asn1Object['contentType'], rfc5652.cmsContentTypesMap) + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + sd = asn1Object['content'] + + self.assertEqual( + rfc5652.CMSVersion().subtype(value='v3'), sd['version']) + self.assertIn( + sd['encapContentInfo']['eContentType'], rfc5652.cmsContentTypesMap) + self.assertEqual( + rfc5035.id_ct_receipt, sd['encapContentInfo']['eContentType']) + + for sa in sd['signerInfos'][0]['signedAttrs']: + self.assertIn(sa['attrType'], rfc5652.cmsAttributesMap) + if sa['attrType'] == rfc5035.id_aa_msgSigDigest: + self.assertIn( + '0x167378', sa['attrValues'][0].prettyPrint()[:10]) + + # Since receipt is inside an OCTET STRING, decodeOpenTypes=True cannot + # automatically decode it + receipt, rest = der_decoder( + sd['encapContentInfo']['eContent'], + asn1Spec=rfc5652.cmsContentTypesMap[sd['encapContentInfo']['eContentType']]) + + self.assertEqual(1, receipt['version']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5083.py b/tests/test_rfc5083.py new file mode 100644 index 0000000..e2eb172 --- /dev/null +++ b/tests/test_rfc5083.py @@ -0,0 +1,95 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley +# Copyright (c) 2018, 2019 Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5083 +from pyasn1_modules import rfc5035 + + +class AuthEnvelopedDataTestCase(unittest.TestCase): + pem_text = """\ +MIICdQIBADGCAiekggIjBgsqhkiG9w0BCRANATCCAhICAQAEE3B0Zi1rbWM6MTM2MTQxMjIx +MTIwDQYLKoZIhvcNAQkQAzAwCwYJYIZIAWUDBAEtMIIBsDCCAawCAQKAFJ7rZ8m5WnTUTS8W +OWaA6AG1y6ScMA0GCSqGSIb3DQEBAQUABIIBgHfnHNqDbyyql2NqX6UQggelWMTjwzJJ1L2e +rbsj1bIAGmpIsUijw+fX8VOS7v1C9ui2Md9NFgCfkmKLo8T/jELqrk7MpMu09G5zDgeXzJfQ +DFc115wbrWAUU3XP7XIb6TNOc3xtq4UxA5V6jNUK2XyWKpjzOtM7gm0VWIJGVVlYu+u32LQc +CjRFb87kvOY/WEnjxQpCW8g+4V747Ud97dYpMub7TLJiRNZkdHnq8xEGKlXjVHSgc10lhphe +1kFGeCpfJEsqjtN7YsVzf65ri9Z+3FJ1IO4cnMDbzGhyRXkS7a0k58/miJbSj88PvzKNSURw +pu4YHMQQX/mjT2ey1SY4ihPMuxxgTdCa04L0UxaRr7xAucz3n2UWShelm3IIjnWRlYdXypnX +vKvwCLoeh5mJwUl1JNFPCQkQ487cKRyobUyNgXQKT4ZDHCgXciwsX5nTsom87Ixp5vqSDJ+D +hXA0r/Caiu1vnY5X9GLHSkqgXkgqgUuu0LfcsQERD8psfQQogbiuZDqJmYt1Iau/pkuGfmee +qeiM3aeQ4NZf9AFZUVWBGArPNHrvVDA3BgkqhkiG9w0BBwEwGwYJYIZIAWUDBAEuMA4EDMr+ +ur76ztut3sr4iIANmvLRbyFUf87+2bPvLQQMoOWSXMGE4BckY8RM +""" + + def setUp(self): + self.asn1Spec = rfc5083.AuthEnvelopedData() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + +class AuthEnvelopedDataOpenTypesTestCase(unittest.TestCase): + pem_text = """\ +MIICvQYLKoZIhvcNAQkQARegggKsMIICqAIBADGCAiekggIjBgsqhkiG9w0BCRAN +ATCCAhICAQAEE3B0Zi1rbWM6MTM2MTQxMjIxMTIwDQYLKoZIhvcNAQkQAzAwCwYJ +YIZIAWUDBAEtMIIBsDCCAawCAQKAFJ7rZ8m5WnTUTS8WOWaA6AG1y6ScMA0GCSqG +SIb3DQEBAQUABIIBgHfnHNqDbyyql2NqX6UQggelWMTjwzJJ1L2erbsj1bIAGmpI +sUijw+fX8VOS7v1C9ui2Md9NFgCfkmKLo8T/jELqrk7MpMu09G5zDgeXzJfQDFc1 +15wbrWAUU3XP7XIb6TNOc3xtq4UxA5V6jNUK2XyWKpjzOtM7gm0VWIJGVVlYu+u3 +2LQcCjRFb87kvOY/WEnjxQpCW8g+4V747Ud97dYpMub7TLJiRNZkdHnq8xEGKlXj +VHSgc10lhphe1kFGeCpfJEsqjtN7YsVzf65ri9Z+3FJ1IO4cnMDbzGhyRXkS7a0k +58/miJbSj88PvzKNSURwpu4YHMQQX/mjT2ey1SY4ihPMuxxgTdCa04L0UxaRr7xA +ucz3n2UWShelm3IIjnWRlYdXypnXvKvwCLoeh5mJwUl1JNFPCQkQ487cKRyobUyN +gXQKT4ZDHCgXciwsX5nTsom87Ixp5vqSDJ+DhXA0r/Caiu1vnY5X9GLHSkqgXkgq +gUuu0LfcsQERD8psfQQogbiuZDqJmYt1Iau/pkuGfmeeqeiM3aeQ4NZf9AFZUVWB +GArPNHrvVDA3BgkqhkiG9w0BBwEwGwYJYIZIAWUDBAEuMA4EDMr+ur76ztut3sr4 +iIANmvLRbyFUf87+2bPvLQQMoOWSXMGE4BckY8RMojEwLwYLKoZIhvcNAQkQAgQx +IDAeDBFXYXRzb24sIGNvbWUgaGVyZQYJKoZIhvcNAQcB +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertIn(asn1Object['contentType'], rfc5652.cmsContentTypesMap) + self.assertEqual(rfc5083.id_ct_authEnvelopedData, asn1Object['contentType']) + + authenv = asn1Object['content'] + + self.assertEqual(0, authenv['version']) + + for attr in authenv['unauthAttrs']: + self.assertIn(attr['attrType'], rfc5652.cmsAttributesMap) + if attr['attrType'] == rfc5035.id_aa_contentHint: + self.assertIn( + 'Watson', attr['attrValues'][0]['contentDescription']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5084.py b/tests/test_rfc5084.py new file mode 100644 index 0000000..c8ad0c2 --- /dev/null +++ b/tests/test_rfc5084.py @@ -0,0 +1,122 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley +# Copyright (c) 2018, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5083 +from pyasn1_modules import rfc5084 +from pyasn1_modules import rfc5652 + + +class CCMParametersTestCase(unittest.TestCase): + ccm_pem_text = "MBEEDE2HVyIurFKUEX8MEgIBBA==" + + def setUp(self): + self.asn1Spec = rfc5084.CCMParameters() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.ccm_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + +class GCMParametersTestCase(unittest.TestCase): + gcm_pem_text = "MBEEDE2HVyIurFKUEX8MEgIBEA==" + + def setUp(self): + self.asn1Spec = rfc5084.GCMParameters() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.gcm_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + +class GCMOpenTypesTestCase(unittest.TestCase): + rfc8591_pem_pext = """\ +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 +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.rfc8591_pem_pext) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual( + rfc5083.id_ct_authEnvelopedData, asn1Object['contentType']) + + aed, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5083.AuthEnvelopedData(), + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(aed.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(aed)) + self.assertEqual(0, aed['version']) + + cea = aed['authEncryptedContentInfo']['contentEncryptionAlgorithm'] + + self.assertEqual(rfc5084.id_aes128_GCM, cea['algorithm']) + self.assertEqual(16, cea['parameters']['aes-ICVlen']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5126.py b/tests/test_rfc5126.py new file mode 100644 index 0000000..e43af9a --- /dev/null +++ b/tests/test_rfc5126.py @@ -0,0 +1,103 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc4055 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5126 + + +class SignedAttributesTestCase(unittest.TestCase): + pem_text = """\ +MYIBUzAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMCsGCSqGSIb3DQEJNDEeMBww +DQYJYIZIAWUDBAIBBQChCwYJKoZIhvcNAQELMC8GCSqGSIb3DQEJBDEiBCCyqtCC +Gosj/GT4YPPAqKheze4A1QBU5O3tniTsVPGr7jBBBgsqhkiG9w0BCRACETEyMDCg +BBMCVVOhBBMCVkGiIjAgExExMjMgU29tZXBsYWNlIFdheRMLSGVybmRvbiwgVkEw +RgYLKoZIhvcNAQkQAi8xNzA1MDMwMTANBglghkgBZQMEAgEFAAQgJPmqUmGQnQ4q +RkVtUHecJXIkozOzX8+pZQj/UD5JcnQwTgYLKoZIhvcNAQkQAg8xPzA9BgorBgEE +AYGsYDAUMC8wCwYJYIZIAWUDBAIBBCDWjjVmAeXgZBkE/rG8Pf8pTCs4Ikowc8Vm +l+AOeKdFgg== +""" + + def setUp(self): + self.asn1Spec = rfc5652.SignedAttributes() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + found_spid_oid = False + + for attr in asn1Object: + if attr['attrType'] in rfc5652.cmsAttributesMap.keys(): + av, rest = der_decoder( + attr['attrValues'][0], + asn1Spec=rfc5652.cmsAttributesMap[attr['attrType']]) + + self.assertFalse(rest) + self.assertTrue(av.prettyPrint()) + self.assertEqual(attr['attrValues'][0], der_encoder(av)) + + if attr['attrType'] == rfc5126.id_aa_ets_sigPolicyId: + spid_oid = rfc5126.SigPolicyId('1.3.6.1.4.1.22112.48.20') + + self.assertEqual( + spid_oid, av['signaturePolicyId']['sigPolicyId']) + + found_spid_oid = True + + self.assertTrue(found_spid_oid) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + attr_type_list = [] + spid_oid = rfc5126.SigPolicyId('1.3.6.1.4.1.22112.48.20') + + for attr in asn1Object: + if attr['attrType'] == rfc5126.id_aa_ets_sigPolicyId: + spid = attr['attrValues'][0]['signaturePolicyId'] + self.assertEqual(spid_oid, spid['sigPolicyId']) + attr_type_list.append(rfc5126.id_aa_ets_sigPolicyId) + + if attr['attrType'] == rfc5126.id_aa_ets_signerLocation: + cn = attr['attrValues'][0]['countryName'] + self.assertEqual('US', cn['printableString']) + attr_type_list.append(rfc5126.id_aa_ets_signerLocation) + + if attr['attrType'] == rfc5126.id_aa_signingCertificateV2: + ha = attr['attrValues'][0]['certs'][0]['hashAlgorithm'] + self.assertEqual(rfc4055.id_sha256, ha['algorithm']) + attr_type_list.append(rfc5126.id_aa_signingCertificateV2) + + self.assertIn(rfc5126.id_aa_ets_sigPolicyId, attr_type_list) + self.assertIn(rfc5126.id_aa_ets_signerLocation, attr_type_list) + self.assertIn(rfc5126.id_aa_signingCertificateV2, attr_type_list) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + import sys + + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5208.py b/tests/test_rfc5208.py index 285085d..4bb684f 100644 --- a/tests/test_rfc5208.py +++ b/tests/test_rfc5208.py @@ -1,10 +1,11 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # import sys +import unittest from pyasn1.codec.der import decoder as der_decoder from pyasn1.codec.der import encoder as der_encoder @@ -12,12 +13,6 @@ from pyasn1_modules import pem from pyasn1_modules import rfc5208 -try: - import unittest2 as unittest - -except ImportError: - import unittest - class PrivateKeyInfoTestCase(unittest.TestCase): pem_text = """\ @@ -38,11 +33,12 @@ def testDerCodec(self): substrate = pem.readBase64fromText(self.pem_text) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + asn1Object, rest = der_decoder.decode( + substrate, asn1Spec=self.asn1Spec) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) class EncryptedPrivateKeyInfoInfoTestCase(unittest.TestCase): @@ -64,14 +60,16 @@ def setUp(self): def testDerCodec(self): substrate = pem.readBase64fromText(self.pem_text) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + asn1Object, rest = der_decoder.decode( + substrate, asn1Spec=self.asn1Spec) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite) + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5275.py b/tests/test_rfc5275.py new file mode 100644 index 0000000..30bce8f --- /dev/null +++ b/tests/test_rfc5275.py @@ -0,0 +1,190 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5275 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc6402 + + +class GLUseKEKTestCase(unittest.TestCase): + pem_text = """\ +MIIMVAYJKoZIhvcNAQcCoIIMRTCCDEECAQMxDTALBglghkgBZQMEAgIwggY7Bggr +BgEFBQcMAqCCBi0EggYpMIIGJTCCBhswggYXAgEBBgsqhkiG9w0BCRAIATGCBgMw +ggX/MEaGLGh0dHBzOi8vd3d3LmV4YW1wbGUuY29tL2xpc3QtaW5mby9ncm91cC1s +aXN0gRZncm91cC1saXN0QGV4YW1wbGUuY29tMIIFmzCCBZekQTA/MQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xETAPBgNVBAoTCEJv +Z3VzIENBgRxncm91cC1saXN0LW93bmVyQGV4YW1wbGUuY29tMIIFMqCCBS4wggTU +oAMCAQICFCVehe2QOuzvkY+pMECid/MyYVKJMAsGCWCGSAFlAwQDAjA/MQswCQYD +VQQGEwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xETAPBgNVBAoT +CEJvZ3VzIENBMB4XDTE5MTAyMDE5MzE1MloXDTIxMTAxOTE5MzE1MlowPzELMAkG +A1UEBhMCVVMxCzAJBgNVBAgTAlZBMRAwDgYDVQQHEwdIZXJuZG9uMREwDwYDVQQK +EwhCb2d1cyBDQTCCA0cwggI5BgcqhkjOOAQBMIICLAKCAQEAt9x/0iwGww3k19h+ +wbODVK1yqjFzEY2pyfXthHcn+nEw+DpURJ+iOhYPr68E3XO5sB48r5xTZhPN5+Ye +jD3T8qhnDtiq4qrrSH7BOaEzqCDpHE2Bpoy3SodQ5Obaiu9Kx1ixBRk/oRZUH+F+ +ATZmF0rPKrZGZOnmsh0IZm3dlmRR9FRGn0aJlZKXveqp+hZ97/r0cbSo6wdT47AP +focgweZMvgWu1IQBs6FiunRgaeX3RyLr4fnkvCzUM7TmxpRJYtL6myAp007QvtgQ +0AdEwVfNl3jQ0IIW7TtpXVxDDQaKZZe9yYrY4GV3etlYk8a4cpjNrBxBCCTMASE4 ++iVtPQIhAJGPJRq8r3GSP6cV7V8EmlxC9ne+xkhiAjBmWtcDibXRAoIBACDebX29 +ZzVOUeaR6ovCC8c3RR93LDlrFa1zyogkZnUx7OHIvIPhFTRUUJKhwkIJ7aTaRLY/ +a9ARFllhyf+cJi6KzAKM4JufAqjN9pNncVzUo4K1vgQRy6T+2Hlc2FYJgknsdqzK +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 +""" + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + + layers = { } + layers.update(rfc5652.cmsContentTypesMap) + + getNextLayer = { + rfc5652.id_ct_contentInfo: lambda x: x['contentType'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContentType'], + rfc6402.id_cct_PKIData: lambda x: None + } + + getNextSubstrate = { + rfc5652.id_ct_contentInfo: lambda x: x['content'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContent'], + rfc6402.id_cct_PKIData: lambda x: None + } + + next_layer = rfc5652.id_ct_contentInfo + while next_layer: + asn1Object, rest = der_decoder( + substrate, asn1Spec=layers[next_layer]) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + substrate = getNextSubstrate[next_layer](asn1Object) + next_layer = getNextLayer[next_layer](asn1Object) + + found_gl_use_kek = False + for ctrl in asn1Object['controlSequence']: + if ctrl['attrType'] == rfc5275.id_skd_glUseKEK: + cv, rest = der_decoder( + ctrl['attrValues'][0], + asn1Spec=rfc5652.cmsAttributesMap[ctrl['attrType']]) + + self.assertFalse(rest) + self.assertTrue(cv.prettyPrint()) + self.assertEqual(ctrl['attrValues'][0], der_encoder(cv)) + + self.assertIn( + 'example.com', + cv['glInfo']['glAddress']['rfc822Name']) + + self.assertIn( + 'example.com', + cv['glOwnerInfo'][0]['glOwnerAddress']['rfc822Name']) + + self.assertEqual(31, cv['glKeyAttributes']['duration']) + found_gl_use_kek = True + + self.assertTrue(found_gl_use_kek) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=rfc5652.ContentInfo(), decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + sd = asn1Object['content'] + self.assertEqual( + rfc6402.id_cct_PKIData, sd['encapContentInfo']['eContentType']) + + pkid, rest = der_decoder( + sd['encapContentInfo']['eContent'], + asn1Spec=rfc6402.PKIData(), + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(pkid.prettyPrint()) + self.assertEqual(sd['encapContentInfo']['eContent'], der_encoder(pkid)) + + found_gl_use_kek = False + for ctrl in pkid['controlSequence']: + if ctrl['attrType'] == rfc5275.id_skd_glUseKEK: + cv = ctrl['attrValues'][0] + + self.assertIn( + 'example.com', + cv['glInfo']['glAddress']['rfc822Name']) + + self.assertIn( + 'example.com', + cv['glOwnerInfo'][0]['glOwnerAddress']['rfc822Name']) + + self.assertEqual(31, cv['glKeyAttributes']['duration']) + found_gl_use_kek = True + + self.assertTrue(found_gl_use_kek) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + import sys + + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5280.py b/tests/test_rfc5280.py index 852f4ca..ea9e533 100644 --- a/tests/test_rfc5280.py +++ b/tests/test_rfc5280.py @@ -1,23 +1,19 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # import sys +import unittest -from pyasn1.codec.der import decoder as der_decoder -from pyasn1.codec.der import encoder as der_encoder +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ from pyasn1_modules import pem from pyasn1_modules import rfc5280 -try: - import unittest2 as unittest - -except ImportError: - import unittest - class CertificateTestCase(unittest.TestCase): pem_text = """\ @@ -46,11 +42,12 @@ def testDerCodec(self): substrate = pem.readBase64fromText(self.pem_text) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) class CertificateListTestCase(unittest.TestCase): @@ -71,15 +68,186 @@ def setUp(self): def testDerCodec(self): substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + +class CertificateOpenTypeTestCase(unittest.TestCase): + pem_text = """\ +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy +NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD +cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs +2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY +JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE +Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ +n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A +PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + + substrate = pem.readBase64fromText(self.pem_text) + + openTypesMap = { + univ.ObjectIdentifier('1.2.840.113549.1.1.1'): univ.Null(""), + univ.ObjectIdentifier('1.2.840.113549.1.1.5'): univ.Null(""), + univ.ObjectIdentifier('1.2.840.113549.1.1.11'): univ.Null(""), + } + + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, openTypes=openTypesMap, + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + sig_alg = asn1Object['tbsCertificate']['signature'] + + self.assertEqual(univ.Null(""), sig_alg['parameters']) + + spki_alg = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + + self.assertEqual(univ.Null(""), spki_alg['parameters']) + + for rdn in asn1Object['tbsCertificate']['subject']['rdnSequence']: + for atv in rdn: + if atv['type'] == rfc5280.id_emailAddress: + self.assertIn("valicert.com", atv['value']) + else: + atv_ps = str(atv['value']['printableString']) + self.assertIn("valicert", atv_ps.lower()) + + +class CertificateListOpenTypeTestCase(unittest.TestCase): + pem_text = """\ +MIIBVjCBwAIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJBVTETMBEGA1UE +CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk +MRUwEwYDVQQDEwxzbm1wbGFicy5jb20xIDAeBgkqhkiG9w0BCQEWEWluZm9Ac25t +cGxhYnMuY29tFw0xMjA0MTExMzQwNTlaFw0xMjA1MTExMzQwNTlaoA4wDDAKBgNV +HRQEAwIBATANBgkqhkiG9w0BAQUFAAOBgQC1D/wwnrcY/uFBHGc6SyoYss2kn+nY +RTwzXmmldbNTCQ03x5vkWGGIaRJdN8QeCzbEi7gpgxgpxAx6Y5WkxkMQ1UPjNM5n +DGVDOtR0dskFrrbHuNpWqWrDaBN0/ryZiWKjr9JRbrpkHgVY29I1gLooQ6IHuKHY +vjnIhxTFoCb5vA== +""" + + def setUp(self): + self.asn1Spec = rfc5280.CertificateList() + + def testDerCodec(self): + + substrate = pem.readBase64fromText(self.pem_text) + + openTypesMap = { + univ.ObjectIdentifier('1.2.840.113549.1.1.1'): univ.Null(""), + univ.ObjectIdentifier('1.2.840.113549.1.1.5'): univ.Null(""), + univ.ObjectIdentifier('1.2.840.113549.1.1.11'): univ.Null(""), + } + + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, openTypes=openTypesMap, + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + sig_alg = asn1Object['tbsCertList']['signature'] + + self.assertEqual(univ.Null(""), sig_alg['parameters']) + + for rdn in asn1Object['tbsCertList']['issuer']['rdnSequence']: + for atv in rdn: + if atv['type'] == rfc5280.id_emailAddress: + self.assertIn("snmplabs.com", atv['value']) + + elif atv['type'] == rfc5280.id_at_countryName: + self.assertEqual('AU', atv['value']) + + else: + self.assertLess(9, len(atv['value']['printableString'])) + + crl_extn_count = 0 + + for extn in asn1Object['tbsCertList']['crlExtensions']: + if extn['extnID'] in rfc5280.certificateExtensionsMap.keys(): + ev, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertFalse(rest) + self.assertTrue(ev.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(ev)) + + crl_extn_count += 1 + + self.assertEqual(1, crl_extn_count) + + def testExtensionsMap(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + cert_extn_count = 0 + + for extn in asn1Object['tbsCertList']['crlExtensions']: + if extn['extnID'] in rfc5280.certificateExtensionsMap.keys(): + extnValue, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + cert_extn_count += 1 + + self.assertEqual(1, cert_extn_count) + + +class ORAddressOpenTypeTestCase(unittest.TestCase): + oraddress_pem_text = """\ +MEMwK2EEEwJHQmIKEwhHT0xEIDQwMKIHEwVVSy5BQ4MHU2FsZm9yZKYFEwNSLUQx +FDASgAEBoQ0TC1N0ZXZlIEtpbGxl +""" + + def setUp(self): + self.asn1Spec = rfc5280.ORAddress() + + def testDecodeOpenTypes(self): + substrate = pem.readBase64fromText(self.oraddress_pem_text) + + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) - asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + ea0 = asn1Object['extension-attributes'][0] - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertEqual(rfc5280.common_name, ea0['extension-attribute-type']) + self.assertEqual("Steve Kille", ea0['extension-attribute-value']) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite) + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5480.py b/tests/test_rfc5480.py new file mode 100755 index 0000000..72ca51a --- /dev/null +++ b/tests/test_rfc5480.py @@ -0,0 +1,81 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5480 + + +class ECCertTestCase(unittest.TestCase): + digicert_ec_cert_pem_text = """\ +MIIDrDCCApSgAwIBAgIQCssoukZe5TkIdnRw883GEjANBgkqhkiG9w0BAQwFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0xMzAzMDgxMjAwMDBaFw0yMzAzMDgxMjAwMDBaMEwxCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJjAkBgNVBAMTHURpZ2lDZXJ0IEVDQyBT +ZWN1cmUgU2VydmVyIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE4ghC6nfYJN6g +LGSkE85AnCNyqQIKDjc/ITa4jVMU9tWRlUvzlgKNcR7E2Munn17voOZ/WpIRllNv +68DLP679Wz9HJOeaBy6Wvqgvu1cYr3GkvXg6HuhbPGtkESvMNCuMo4IBITCCAR0w +EgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwNAYIKwYBBQUHAQEE +KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQgYDVR0f +BDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xv +YmFsUm9vdENBLmNybDA9BgNVHSAENjA0MDIGBFUdIAAwKjAoBggrBgEFBQcCARYc +aHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAdBgNVHQ4EFgQUo53mH/naOU/A +buiRy5Wl2jHiCp8wHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJ +KoZIhvcNAQEMBQADggEBAMeKoENL7HTJxavVHzA1Nm6YVntIrAVjrnuaVyRXzG/6 +3qttnMe2uuzO58pzZNvfBDcKAEmzP58mrZGMIOgfiA4q+2Y3yDDo0sIkp0VILeoB +UEoxlBPfjV/aKrtJPGHzecicZpIalir0ezZYoyxBEHQa0+1IttK7igZFcTMQMHp6 +mCHdJLnsnLWSB62DxsRq+HfmNb4TDydkskO/g+l3VtsIh5RHFPVfKK+jaEyDj2D3 +loB5hWp2Jp2VDCADjT7ueihlZGak2YPqmXTNbk19HOuNssWvFhtOyPNV6og4ETQd +Ea8/B6hPatJ0ES8q/HO3X8IVQwVs1n3aAr0im0/T+Xc= +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.digicert_ec_cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + algid = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + + self.assertEqual(rfc5480.id_ecPublicKey, algid['algorithm']) + + param, rest = der_decoder(algid['parameters'], asn1Spec=rfc5480.ECParameters()) + + self.assertTrue(param.prettyPrint()) + self.assertEqual(rfc5480.secp384r1, param['namedCurve']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.digicert_ec_cert_pem_text) + asn1Object, rest = der_decoder(substrate, + asn1Spec=self.asn1Spec, decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + spki_alg = asn1Object['tbsCertificate']['subjectPublicKeyInfo']['algorithm'] + + self.assertEqual(rfc5480.id_ecPublicKey, spki_alg['algorithm']) + self.assertEqual(rfc5480.secp384r1, spki_alg['parameters']['namedCurve']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5636.py b/tests/test_rfc5636.py new file mode 100644 index 0000000..8f5d90e --- /dev/null +++ b/tests/test_rfc5636.py @@ -0,0 +1,118 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5636 + + +class TraceableAnonymousCertificateTestCase(unittest.TestCase): + pem_text = """\ +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 +""" + + def testDerCodec(self): + + substrate = pem.readBase64fromText(self.pem_text) + + layers = { } + layers.update(rfc5652.cmsContentTypesMap) + + getNextLayer = { + rfc5652.id_ct_contentInfo: lambda x: x['contentType'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContentType'], + rfc5636.id_kisa_tac_token: lambda x: None + } + + getNextSubstrate = { + rfc5652.id_ct_contentInfo: lambda x: x['content'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContent'], + rfc5636.id_kisa_tac_token: lambda x: None + } + + next_layer = rfc5652.id_ct_contentInfo + while next_layer: + asn1Object, rest = der_decoder( + substrate, asn1Spec=layers[next_layer]) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + substrate = getNextSubstrate[next_layer](asn1Object) + next_layer = getNextLayer[next_layer](asn1Object) + + self.assertEqual('2019', asn1Object['timeout'][:4]) + self.assertEqual('5dcdf44e', asn1Object['userKey'].prettyPrint()[-8:]) + + def testOpenTypes(self): + asn1Spec=rfc5652.ContentInfo() + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + substrate = asn1Object['content']['encapContentInfo']['eContent'] + oid = asn1Object['content']['encapContentInfo']['eContentType'] + self.assertIn(oid, rfc5652.cmsContentTypesMap) + + tac_token, rest = der_decoder( + substrate, + asn1Spec=rfc5652.cmsContentTypesMap[oid], + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(tac_token.prettyPrint()) + self.assertEqual(substrate, der_encoder(tac_token)) + + self.assertEqual('2019', tac_token['timeout'][:4]) + self.assertEqual('5dcdf44e', tac_token['userKey'].prettyPrint()[-8:]) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5639.py b/tests/test_rfc5639.py new file mode 100644 index 0000000..628b902 --- /dev/null +++ b/tests/test_rfc5639.py @@ -0,0 +1,80 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5480 +from pyasn1_modules import rfc5639 + + +class ECCertTestCase(unittest.TestCase): + brainpool_ec_cert_pem_text = """\ +MIIB0jCCAXmgAwIBAgITPUXQAyl3ZE5iAHYGZYSp1FkqzTAKBggqhkjOPQQDAjA/ +MQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkExEDAOBgNVBAcMB0hlcm5kb24xETAP +BgNVBAoMCEJvZ3VzIENBMB4XDTE5MTIwOTIxNDM0NFoXDTIxMTIwODIxNDM0NFow +PzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMRAwDgYDVQQHDAdIZXJuZG9uMREw +DwYDVQQKDAhCb2d1cyBDQTBaMBQGByqGSM49AgEGCSskAwMCCAEBBwNCAASBvvOk +WNZlGAf5O3V94qgC3IUUR/6uxFxT6To0ULFmrVVndXiVP6DE5h5QHGXPwKfO+4Yt +n0OVnGHp68dPS37Go1MwUTAdBgNVHQ4EFgQUiRFFVcdn6Fp9+sEP1GVRtwl9XgIw +HwYDVR0jBBgwFoAUiRFFVcdn6Fp9+sEP1GVRtwl9XgIwDwYDVR0TAQH/BAUwAwEB +/zAKBggqhkjOPQQDAgNHADBEAiB3d+P64Dh5YzwyM++uOL6zHUeLbNpW2sF1eJsm +l3M5uQIgGxpbAXOt/o1xtyhEGLNUBE7ObgQpm7tHMMQGUHo4wV8= +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.brainpool_ec_cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + spki = asn1Object['tbsCertificate']['subjectPublicKeyInfo'] + algid = spki['algorithm'] + + self.assertEqual(rfc5480.id_ecPublicKey, algid['algorithm']) + + param, rest = der_decoder( + algid['parameters'], asn1Spec=rfc5480.ECParameters()) + + self.assertFalse(rest) + self.assertTrue(param.prettyPrint()) + self.assertEqual(algid['parameters'], der_encoder(param)) + + self.assertEqual(rfc5639.brainpoolP256r1, param['namedCurve']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.brainpool_ec_cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + spki = asn1Object['tbsCertificate']['subjectPublicKeyInfo'] + algid = spki['algorithm'] + + self.assertEqual(rfc5480.id_ecPublicKey, algid['algorithm']) + self.assertEqual( + rfc5639.brainpoolP256r1, algid['parameters']['namedCurve']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5649.py b/tests/test_rfc5649.py new file mode 100644 index 0000000..c2fa9d1 --- /dev/null +++ b/tests/test_rfc5649.py @@ -0,0 +1,56 @@ +# +# 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 +import unittest + +from pyasn1.codec.der import decoder as der_decoder +from pyasn1.codec.der import encoder as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5649 + + +class AESKeyWrapTestCase(unittest.TestCase): + kw_alg_id_pem_text = "MAsGCWCGSAFlAwQBLQ==" + + def setUp(self): + self.asn1Spec = rfc5649.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.kw_alg_id_pem_text) + asn1Object, rest = der_decoder.decode( + substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(rfc5649.id_aes256_wrap, asn1Object[0]) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + +class AESKeyWrapWithPadTestCase(unittest.TestCase): + kw_pad_alg_id_pem_text = "MAsGCWCGSAFlAwQBMA==" + + def setUp(self): + self.asn1Spec = rfc5649.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.kw_pad_alg_id_pem_text) + asn1Object, rest = der_decoder.decode( + substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(rfc5649.id_aes256_wrap_pad, asn1Object[0]) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5652.py b/tests/test_rfc5652.py index a2d1fc7..7055b52 100644 --- a/tests/test_rfc5652.py +++ b/tests/test_rfc5652.py @@ -1,24 +1,22 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # import sys +import unittest from pyasn1.codec.der import decoder as der_decoder from pyasn1.codec.der import encoder as der_encoder +from pyasn1.type import char +from pyasn1.type import namedtype +from pyasn1.type import univ from pyasn1_modules import pem from pyasn1_modules import rfc5652 from pyasn1_modules import rfc6402 -try: - import unittest2 as unittest - -except ImportError: - import unittest - class ContentInfoTestCase(unittest.TestCase): pem_text = """\ @@ -68,7 +66,6 @@ def testDerCodec(self): rfc6402.id_cct_PKIData: lambda x: None } - next_layer = rfc5652.id_ct_contentInfo while next_layer: @@ -77,15 +74,96 @@ def testDerCodec(self): substrate, asn1Spec=layers[next_layer] ) - assert not rest - assert asn1Object.prettyPrint() - assert der_encoder.encode(asn1Object) == substrate + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) substrate = getNextSubstrate[next_layer](asn1Object) next_layer = getNextLayer[next_layer](asn1Object) + def testOpenTypes(self): + class ClientInformation(univ.Sequence): + pass + + ClientInformation.componentType = namedtype.NamedTypes( + namedtype.NamedType('clientId', univ.Integer()), + namedtype.NamedType('MachineName', char.UTF8String()), + namedtype.NamedType('UserName', char.UTF8String()), + namedtype.NamedType('ProcessName', char.UTF8String()) + ) + + class EnrollmentCSP(univ.Sequence): + pass + + EnrollmentCSP.componentType = namedtype.NamedTypes( + namedtype.NamedType('KeySpec', univ.Integer()), + namedtype.NamedType('Name', char.BMPString()), + namedtype.NamedType('Signature', univ.BitString()) + ) + + openTypeMap = { + # attributes + univ.ObjectIdentifier('1.3.6.1.4.1.311.13.2.3'): char.IA5String(), + univ.ObjectIdentifier('1.3.6.1.4.1.311.13.2.2'): EnrollmentCSP(), + univ.ObjectIdentifier('1.3.6.1.4.1.311.21.20'): ClientInformation(), + # algorithm identifier parameters + univ.ObjectIdentifier('1.2.840.113549.1.1.1'): univ.Null(""), + univ.ObjectIdentifier('1.2.840.113549.1.1.5'): univ.Null(""), + univ.ObjectIdentifier('1.2.840.113549.1.1.11'): univ.Null(""), + } + + openTypeMap.update(rfc5652.cmsAttributesMap) + openTypeMap.update(rfc6402.cmcControlAttributesMap) + + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder.decode(substrate, + asn1Spec=rfc5652.ContentInfo(), decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + eci = asn1Object['content']['encapContentInfo'] + + self.assertIn(eci['eContentType'], rfc5652.cmsContentTypesMap) + self.assertEqual(rfc6402.id_cct_PKIData, eci['eContentType']) + + pkid, rest = der_decoder.decode(eci['eContent'], + asn1Spec=rfc5652.cmsContentTypesMap[eci['eContentType']], + openTypes=openTypeMap, + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(pkid.prettyPrint()) + self.assertEqual(eci['eContent'], der_encoder.encode(pkid)) + + for req in pkid['reqSequence']: + cr = req['tcr']['certificationRequest'] + + sig_alg = cr['signatureAlgorithm'] + + self.assertIn(sig_alg['algorithm'], openTypeMap) + self.assertEqual(univ.Null(""), sig_alg['parameters']) + + cri = cr['certificationRequestInfo'] + spki_alg = cri['subjectPublicKeyInfo']['algorithm'] + + self.assertIn( spki_alg['algorithm'], openTypeMap) + self.assertEqual(univ.Null(""), spki_alg['parameters']) + + attrs = cr['certificationRequestInfo']['attributes'] + + for attr in attrs: + self.assertIn(attr['attrType'], openTypeMap) + + if attr['attrType'] == univ.ObjectIdentifier('1.3.6.1.4.1.311.13.2.3'): + self.assertEqual("6.2.9200.2", attr['attrValues'][0]) + + else: + self.assertTrue(attr['attrValues'][0].hasValue()) + suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite) + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5697.py b/tests/test_rfc5697.py new file mode 100644 index 0000000..1aa0e2b --- /dev/null +++ b/tests/test_rfc5697.py @@ -0,0 +1,126 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5697 + + +class OtherCertTestCase(unittest.TestCase): + cert_pem_text = """\ +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 +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + other_cert_found = False + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5697.id_pe_otherCerts: + extnValue, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5697.OtherCertificates()) + + self.assertFalse(rest) + self.assertTrue(extnValue.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + self.assertEqual( + 11939979568329289287, + extnValue[0]['issuerSerial']['serialNumber']) + + other_cert_found = True + + self.assertTrue(other_cert_found) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + other_cert_found = False + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5697.id_pe_otherCerts: + self.assertIn(extn['extnID'], rfc5280.certificateExtensionsMap) + + extnValue, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']], + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(extnValue.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + self.assertEqual( + 11939979568329289287, + extnValue[0]['issuerSerial']['serialNumber']) + + other_cert_found = True + + self.assertTrue(other_cert_found) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5751.py b/tests/test_rfc5751.py new file mode 100644 index 0000000..7ce4373 --- /dev/null +++ b/tests/test_rfc5751.py @@ -0,0 +1,103 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5751 + + +class SignedMessageTestCase(unittest.TestCase): + pem_text = """\ +MIIGigYJKoZIhvcNAQcCoIIGezCCBncCAQExCTAHBgUrDgMCGjArBgkqhkiG9w0B +BwGgHgQcVGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50LqCCAuAwggLcMIICm6AD +AgECAgIAyDAJBgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOTkwODE3 +MDExMDQ5WhcNMzkxMjMxMjM1OTU5WjATMREwDwYDVQQDEwhBbGljZURTUzCCAbYw +ggErBgcqhkjOOAQBMIIBHgKBgQCBjc3tg+oKnjk+wkgoo+RHk90O16gO7FPFq4QI +T/+U4XNIfgzW80RI0f6fr6ShiS/h2TDINt4/m7+3TNxfaYrkddA3DJEIlZvep175 +/PSfL91DqItU8T+wBwhHTV2Iw8O1s+NVCHXVOXYQxHi9/52whJc38uRRG7XkCZZc +835b2wIVAOJHphpFZrgTxtqPuDchK2KL95PNAoGAJjjQFIkyqjn7Pm3ZS1lqTHYj +OQQCNVzyyxowwx5QXd2bWeLNqgU9WMB7oja4bgevfYpCJaf0dc9KCF5LPpD4beqc +ySGKO3YU6c4uXaMHzSOFuC8wAXxtSYkRiTZEvfjIlUpTVrXi+XPsGmE2HxF/wr3t +0VD/mHTC0YFKYDm6NjkDgYQAAoGAXOO5WnUUlgupet3jP6nsrF7cvbcTETSmFoko +ESPZNIZndXUTEj1DW2/lUb/6ifKiGz4kfT0HjVtjyLtFpaBK44XWzgaAP+gjfhry +JKtTGrgnDR7vCL9mFIBcYqxl+hWL8bs01NKWN/ZhR7LEMoTwfkFA/UanY04z8qXi +9PKD5bijgYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSME +GDAWgBRwRD6CLm+H3krTdeM9ILxDK5PxHzAdBgNVHQ4EFgQUvmyhs+PB9+1DcKTO +EwHi/eOX/s0wHwYDVR0RBBgwFoEUQWxpY2VEU1NAZXhhbXBsZS5jb20wCQYHKoZI +zjgEAwMwADAtAhRVDKQZH0IriXEiM42DarU9Z2u/RQIVAJ9hU1JUC1yy3drndh3i +EFJbQ169MYIDVDCCA1ACAQEwGDASMRAwDgYDVQQDEwdDYXJsRFNTAgIAyDAHBgUr +DgMCGqCCAuowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAjBgkqhkiG9w0BCQQx +FgQUQGrsCFJ5um4WAi2eBinAIpaH3UgwOAYDKqszMTEEL1RoaXMgaXMgYSB0ZXN0 +IEdlbmVyYWwgQVNOIEF0dHJpYnV0ZSwgbnVtYmVyIDEuMD4GCyqGSIb3DQEJEAIE +MS8wLQwgQ29udGVudCBIaW50cyBEZXNjcmlwdGlvbiBCdWZmZXIGCSqGSIb3DQEH +ATBKBgkqhkiG9w0BCQ8xPTA7MAcGBSoDBAUGMDAGBioDBAUGTQQmU21pbWUgQ2Fw +YWJpbGl0aWVzIHBhcmFtZXRlcnMgYnVmZmVyIDIwbwYLKoZIhvcNAQkQAgoxYDBe +BgUqAwQFBgQrQ29udGVudCBSZWZlcmVuY2UgQ29udGVudCBJZGVudGlmaWVyIEJ1 +ZmZlcgQoQ29udGVudCBSZWZlcmVuY2UgU2lnbmF0dXJlIFZhbHVlIEJ1ZmZlcjBz +BgsqhkiG9w0BCRACCzFkoGIwWjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDVVTIEdv +dmVybm1lbnQxETAPBgNVBAsTCFZEQSBTaXRlMQwwCgYDVQQLEwNWREExEjAQBgNV +BAMTCURhaXN5IFJTQQIEClVEMzCB/AYLKoZIhvcNAQkQAgMxgewwgekwgeYEBzU3 +MzgyOTkYDzE5OTkwMzExMTA0NDMzWqGByTCBxqRhMF8xCzAJBgNVBAYTAlVTMRYw +FAYDVQQKEw1VUyBHb3Zlcm5tZW50MREwDwYDVQQLEwhWREEgU2l0ZTEMMAoGA1UE +CxMDVkRBMRcwFQYDVQQDEw5CdWdzIEJ1bm55IERTQaRhMF8xCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1VUyBHb3Zlcm5tZW50MREwDwYDVQQLEwhWREEgU2l0ZTEMMAoG +A1UECxMDVkRBMRcwFQYDVQQDEw5FbG1lciBGdWRkIERTQTAJBgcqhkjOOAQDBC8w +LQIVALwzN2XE93BcF0kTqkyFyrtSkUhZAhRjlqIUi89X3rBIX2xk3YQESV8cyg== +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + smimeCapMap = { + univ.ObjectIdentifier('1.2.3.4.5.6.77'): univ.OctetString(), + } + smimeCapMap.update(rfc5751.smimeCapabilityMap) + + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder (substrate, + asn1Spec=self.asn1Spec, + decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + self.assertEqual(1, asn1Object['content']['version']) + + for si in asn1Object['content']['signerInfos']: + self.assertEqual(1, si['version']) + + for attr in si['signedAttrs']: + + if attr['attrType'] == rfc5751.smimeCapabilities: + for scap in attr['attrValues'][0]: + if scap['capabilityID'] in smimeCapMap.keys(): + scap_p, rest = der_decoder(scap['parameters'], + asn1Spec=smimeCapMap[scap['capabilityID']]) + self.assertFalse(rest) + self.assertEqual(scap['parameters'], der_encoder(scap_p)) + self.assertIn('parameters', scap_p.prettyPrint()) + + if attr['attrType'] == rfc5751.id_aa_encrypKeyPref: + ekp_issuer_serial = attr['attrValues'][0]['issuerAndSerialNumber'] + + self.assertEqual(173360179, ekp_issuer_serial['serialNumber']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5752.py b/tests/test_rfc5752.py new file mode 100644 index 0000000..7677632 --- /dev/null +++ b/tests/test_rfc5752.py @@ -0,0 +1,207 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc4055 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5752 + + +class MultipleSignaturesTestCase(unittest.TestCase): + pem_text = """\ +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 +""" + + def setUp(self): + self.asn1Spec = rfc5652.SignedAttributes() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + + layers = { } + layers.update(rfc5652.cmsContentTypesMap) + + getNextLayer = { + rfc5652.id_ct_contentInfo: lambda x: x['contentType'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContentType'], + rfc5652.id_data: lambda x: None + } + + getNextSubstrate = { + rfc5652.id_ct_contentInfo: lambda x: x['content'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContent'], + rfc5652.id_data: lambda x: None + } + + next_layer = rfc5652.id_ct_contentInfo + while not next_layer == rfc5652.id_data: + asn1Object, rest = der_decoder( + substrate, asn1Spec=layers[next_layer]) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + if next_layer == rfc5652.id_signedData: + signerInfos = asn1Object['signerInfos'] + + substrate = getNextSubstrate[next_layer](asn1Object) + next_layer = getNextLayer[next_layer](asn1Object) + + found_mult_sig1 = False + for attr in signerInfos[0]['signedAttrs']: + if attr['attrType'] in rfc5652.cmsAttributesMap: + av, rest = der_decoder( + attr['attrValues'][0], + asn1Spec=rfc5652.cmsAttributesMap[attr['attrType']]) + + self.assertFalse(rest) + self.assertTrue(av.prettyPrint()) + self.assertEqual(attr['attrValues'][0], der_encoder(av)) + + if attr['attrType'] == rfc5752.id_aa_multipleSignatures: + self.assertEqual( + av['bodyHashAlg']['algorithm'], rfc4055.id_sha384) + + self.assertEqual( + 'dfaf6c0a', + av['signAttrsHash']['hash'].prettyPrint()[2:10]) + + found_mult_sig1 = True + + found_mult_sig2 = False + for attr in signerInfos[1]['signedAttrs']: + if attr['attrType'] in rfc5652.cmsAttributesMap: + av, rest = der_decoder( + attr['attrValues'][0], + asn1Spec=rfc5652.cmsAttributesMap[attr['attrType']]) + + self.assertFalse(rest) + self.assertTrue(av.prettyPrint()) + self.assertEqual(attr['attrValues'][0], der_encoder(av)) + + if attr['attrType'] == rfc5752.id_aa_multipleSignatures: + self.assertEqual( + av['bodyHashAlg']['algorithm'], rfc4055.id_sha256) + + self.assertEqual( + '7329527d', + av['signAttrsHash']['hash'].prettyPrint()[2:10]) + + found_mult_sig2 = True + + self.assertTrue(found_mult_sig1) + self.assertTrue(found_mult_sig2) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=rfc5652.ContentInfo(), decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + found_mult_sig1 = False + for attr in asn1Object['content']['signerInfos'][0]['signedAttrs']: + if attr['attrType'] == rfc5752.id_aa_multipleSignatures: + av = attr['attrValues'][0] + + self.assertEqual( + av['bodyHashAlg']['algorithm'], rfc4055.id_sha384) + + self.assertEqual( + 'dfaf6c0a', + av['signAttrsHash']['hash'].prettyPrint()[2:10]) + + found_mult_sig1 = True + + found_mult_sig2 = False + for attr in asn1Object['content']['signerInfos'][1]['signedAttrs']: + if attr['attrType'] == rfc5752.id_aa_multipleSignatures: + av = attr['attrValues'][0] + + self.assertEqual( + av['bodyHashAlg']['algorithm'], rfc4055.id_sha256) + + self.assertEqual( + '7329527d', + av['signAttrsHash']['hash'].prettyPrint()[2:10]) + + found_mult_sig2 = True + + self.assertTrue(found_mult_sig1) + self.assertTrue(found_mult_sig2) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + import sys + + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5753.py b/tests/test_rfc5753.py new file mode 100644 index 0000000..7bb44ef --- /dev/null +++ b/tests/test_rfc5753.py @@ -0,0 +1,129 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc3565 +from pyasn1_modules import rfc5480 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5753 + + +class EnvelopedDataTestCase(unittest.TestCase): + pem_text = """\ +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 +ns9dHqSvkg== +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_envelopedData, asn1Object['contentType']) + + ed, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.EnvelopedData()) + self.assertFalse(rest) + self.assertTrue(ed.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(ed)) + + opk_ai_p = rfc5480.ECParameters() + opk_ai_p['namedCurve'] = rfc5480.secp384r1 + + kwai = rfc5753.KeyWrapAlgorithm() + kwai['algorithm'] = rfc3565.id_aes256_wrap + + ukm_found = False + self.assertEqual(ed['version'], rfc5652.CMSVersion(value=2)) + for ri in ed['recipientInfos']: + self.assertEqual(ri['kari']['version'], rfc5652.CMSVersion(value=3)) + opk_alg = ri['kari']['originator']['originatorKey']['algorithm'] + self.assertEqual(opk_alg['algorithm'], rfc5753.id_ecPublicKey) + self.assertEqual(opk_alg['parameters'], der_encoder(opk_ai_p)) + kek_alg = ri['kari']['keyEncryptionAlgorithm'] + self.assertEqual(kek_alg['algorithm'], rfc5753.dhSinglePass_stdDH_sha384kdf_scheme) + self.assertEqual(kek_alg['parameters'], der_encoder(kwai)) + ukm = ri['kari']['ukm'] + self.assertEqual(ukm, rfc5652.UserKeyingMaterial(hexValue='52464335373533')) + ukm_found = True + + self.assertTrue(ukm_found) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + assert asn1Object['contentType'] == rfc5652.id_envelopedData + ed = asn1Object['content'] + + ukm_found = False + self.assertEqual(ed['version'], rfc5652.CMSVersion(value=2)) + for ri in ed['recipientInfos']: + self.assertEqual(ri['kari']['version'], rfc5652.CMSVersion(value=3)) + opk_alg = ri['kari']['originator']['originatorKey']['algorithm'] + self.assertEqual(opk_alg['algorithm'], rfc5753.id_ecPublicKey) + self.assertEqual(opk_alg['parameters']['namedCurve'], rfc5480.secp384r1) + kek_alg = ri['kari']['keyEncryptionAlgorithm'] + self.assertEqual(kek_alg['algorithm'], rfc5753.dhSinglePass_stdDH_sha384kdf_scheme) + self.assertEqual(kek_alg['parameters']['algorithm'], rfc3565.id_aes256_wrap) + ukm = ri['kari']['ukm'] + self.assertEqual(ukm, rfc5652.UserKeyingMaterial(hexValue='52464335373533')) + ukm_found = True + + self.assertTrue(ukm_found) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5755.py b/tests/test_rfc5755.py new file mode 100644 index 0000000..cf4a05f --- /dev/null +++ b/tests/test_rfc5755.py @@ -0,0 +1,212 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.compat.octets import str2octs + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5755 +from pyasn1_modules import rfc3114 + + +class AttributeCertificateTestCase(unittest.TestCase): + pem_text = """\ +MIIDBTCCAm4CAQEwgY+gUTBKpEgwRjEjMCEGA1UEAwwaQUNNRSBJbnRlcm1lZGlh +dGUgRUNEU0EgQ0ExCzAJBgNVBAYTAkZJMRIwEAYDVQQKDAlBQ01FIEx0ZC4CAx7N +WqE6pDgwNjETMBEGA1UEAwwKQUNNRSBFQ0RTQTELMAkGA1UEBhMCRkkxEjAQBgNV +BAoMCUFDTUUgTHRkLqA9MDukOTA3MRQwEgYDVQQDDAtleGFtcGxlLmNvbTELMAkG +A1UEBhMCRkkxEjAQBgNVBAoMCUFDTUUgTHRkLjANBgkqhkiG9w0BAQsFAAIEC63K +/jAiGA8yMDE2MDEwMTEyMDAwMFoYDzIwMTYwMzAxMTIwMDAwWjCB8jA8BggrBgEF +BQcKATEwMC6GC3VybjpzZXJ2aWNlpBUwEzERMA8GA1UEAwwIdXNlcm5hbWUECHBh +c3N3b3JkMDIGCCsGAQUFBwoCMSYwJIYLdXJuOnNlcnZpY2WkFTATMREwDwYDVQQD +DAh1c2VybmFtZTA1BggrBgEFBQcKAzEpMCegGKQWMBQxEjAQBgNVBAMMCUFDTUUg +THRkLjALDAlBQ01FIEx0ZC4wIAYIKwYBBQUHCgQxFDASMBAMBmdyb3VwMQwGZ3Jv +dXAyMCUGA1UESDEeMA2hC4YJdXJuOnJvbGUxMA2hC4YJdXJuOnJvbGUyMGowHwYD +VR0jBBgwFoAUgJCMhskAsEBzvklAX8yJBOXO500wCQYDVR04BAIFADA8BgNVHTcB +Af8EMjAwMB2gCoYIdXJuOnRlc3SgD4INKi5leGFtcGxlLmNvbTAPoA2GC3Vybjph +bm90aGVyMA0GCSqGSIb3DQEBCwUAA4GBACygfTs6TkPurZQTLufcE3B1H2707OXK +sJlwRpuodR2oJbunSHZ94jcJHs5dfbzFs6vNfVLlBiDBRieX4p+4JcQ2P44bkgyi +UTJu7g1b6C1liB3vO6yH5hOZicOAaKd+c/myuGb9uJ4n6y2oLNxnk/fDzpuZUe2h +Q4eikPk4LQey +""" + + def setUp(self): + self.asn1Spec = rfc5755.AttributeCertificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(1, asn1Object['acinfo']['version']) + + count = 0 + + for attr in asn1Object['acinfo']['attributes']: + self.assertIn(attr['type'], rfc5280.certificateAttributesMap) + + av, rest = der_decoder( + attr['values'][0], + asn1Spec=rfc5280.certificateAttributesMap[attr['type']]) + + self.assertFalse(rest) + self.assertTrue(av.prettyPrint()) + self.assertEqual(attr['values'][0], der_encoder(av)) + + count += 1 + + self.assertEqual(5, count) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, + asn1Spec=self.asn1Spec, + decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(1, asn1Object['acinfo']['version']) + + count = 0 + + for attr in asn1Object['acinfo']['attributes']: + self.assertIn(attr['type'], rfc5280.certificateAttributesMap) + count += 1 + if attr['type'] == rfc5755.id_aca_authenticationInfo: + self.assertEqual( + str2octs('password'), attr['values'][0]['authInfo']) + + self.assertEqual(5, count) + + +class CertificateWithClearanceTestCase(unittest.TestCase): + cert_pem_text = """\ +MIID1DCCA1qgAwIBAgIUUc1IQGJpeYQ0XwOS2ZmVEb3aeZ0wCgYIKoZIzj0EAwMw +ZjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlZBMRAwDgYDVQQHEwdIZXJuZG9uMRAw +DgYDVQQKEwdFeGFtcGxlMQwwCgYDVQQLEwNQQ0ExGDAWBgNVBAMTD3BjYS5leGFt +cGxlLmNvbTAeFw0xOTExMDUyMjIwNDZaFw0yMDExMDQyMjIwNDZaMIGSMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xEDAOBgNVBAoT +B0V4YW1wbGUxIjAgBgNVBAsTGUh1bWFuIFJlc291cmNlIERlcGFydG1lbnQxDTAL +BgNVBAMTBEZyZWQxHzAdBgkqhkiG9w0BCQEWEGZyZWRAZXhhbXBsZS5jb20wdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAAQObFslQ2EBP0xlDJ3sRnsNaqm/woQgKpBispSx +XxK5bWUVpfnWsZnjLWhtDuPcu1BcBlM2g7gwL/aw8nUSIK3D8Ja9rTUQQXc3zxnk +cl8+8znNXHMGByRjPUH87C+TOrqjggGaMIIBljAdBgNVHQ4EFgQU5m711OqFDNGR +SWMOSzTXjpTLIFUwbwYDVR0jBGgwZoAUJuolDwsyICik11oKjf8t3L1/VGWhQ6RB +MD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjER +MA8GA1UECgwIQm9ndXMgQ0GCCQCls1QoG7BuRjAPBgNVHRMBAf8EBTADAQH/MAsG +A1UdDwQEAwIBhjBCBglghkgBhvhCAQ0ENRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5u +b3QgYmUgdHJ1c3RlZCBmb3IgYW55IHB1cnBvc2UuMBUGA1UdIAQOMAwwCgYIKwYB +BQUHDQIwCgYDVR02BAMCAQIwfwYDVR0JBHgwdjBJBgNVBDcxQjBABgsqhkiG9w0B +CRAHAwMCBeAxLTArgAsqhkiG9w0BCRAHBIEcMBoMGEhVTUFOIFJFU09VUkNFUyBV +U0UgT05MWTApBglghkgBZQIBBUQxHAwaSHVtYW4gUmVzb3VyY2VzIERlcGFydG1l +bnQwCgYIKoZIzj0EAwMDaAAwZQIwVh/RypULFgPpAN0I7OvuMomRWnm/Hea3Hk8P +tTRz2Zai8iYat7oeAmGVgMhSXy2jAjEAuJW4l/CFatBy4W/lZ7gS3weBdBa5WEDI +FFMC7GjGtCeLtXYqWfBnRdK26dOaHLB2 +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + clearance_found = False + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectDirectoryAttributes: + self.assertIn(extn['extnID'], rfc5280.certificateExtensionsMap) + + ev, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertFalse(rest) + self.assertTrue(ev.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(ev)) + + for attr in ev: + if attr['type'] == rfc5755.id_at_clearance: + self.assertIn(attr['type'], rfc5280.certificateAttributesMap) + + av, rest = der_decoder( + attr['values'][0], + asn1Spec=rfc5280.certificateAttributesMap[attr['type']]) + + self.assertEqual(rfc3114.id_tsp_TEST_Whirlpool, av['policyId']) + + for cat in av['securityCategories']: + self.assertEqual( + rfc3114.id_tsp_TEST_Whirlpool_Categories, cat['type']) + self.assertIn( + cat['type'], rfc5755.securityCategoryMap) + catv, rest = der_decoder( + cat['value'], + asn1Spec=rfc5755.securityCategoryMap[cat['type']]) + + self.assertIn('USE ONLY', catv[0]) + + clearance_found = True + + self.assertTrue(clearance_found) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + clearance_found = False + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectDirectoryAttributes: + self.assertIn(extn['extnID'], rfc5280.certificateExtensionsMap) + + ev, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']], + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(ev.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(ev)) + + for attr in ev: + if attr['type'] == rfc5755.id_at_clearance: + spid = rfc3114.id_tsp_TEST_Whirlpool + catid = rfc3114.id_tsp_TEST_Whirlpool_Categories + + self.assertEqual(spid, attr['values'][0]['policyId']) + + for cat in attr['values'][0]['securityCategories']: + self.assertEqual(catid, cat['type']) + self.assertIn( u'USE ONLY', cat['value'][0]) + + clearance_found = True + + self.assertTrue(clearance_found) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5913.py b/tests/test_rfc5913.py new file mode 100644 index 0000000..ef59086 --- /dev/null +++ b/tests/test_rfc5913.py @@ -0,0 +1,122 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5913 +from pyasn1_modules import rfc5755 +from pyasn1_modules import rfc3114 + + +class ClearanceTestCase(unittest.TestCase): + cert_pem_text = """\ +MIIDhzCCAw6gAwIBAgIJAKWzVCgbsG5GMAoGCCqGSM49BAMDMD8xCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9n +dXMgQ0EwHhcNMTkxMTAyMTg0MjE4WhcNMjAxMTAxMTg0MjE4WjBmMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xEDAOBgNVBAoTB0V4 +YW1wbGUxDDAKBgNVBAsTA1BDQTEYMBYGA1UEAxMPcGNhLmV4YW1wbGUuY29tMHYw +EAYHKoZIzj0CAQYFK4EEACIDYgAEPf5vbgAqbE5dn6wbiCx4sCCcn1BKSrHmCfiW +C9QLSGVNGHifQwPt9odGXjRiQ7QwpZ2wRD6Z91v+fk85XXLE3kJQCQdPIHFUY5EM +pvS7T6u6xrmwnlVpUURPTOxfc55Oo4IBrTCCAakwHQYDVR0OBBYEFCbqJQ8LMiAo +pNdaCo3/Ldy9f1RlMG8GA1UdIwRoMGaAFPI12zQE2qVV8r1pA5mwYuziFQjBoUOk +QTA/MQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkExEDAOBgNVBAcMB0hlcm5kb24x +ETAPBgNVBAoMCEJvZ3VzIENBggkA6JHWBpFPzvIwDwYDVR0TAQH/BAUwAwEB/zAL +BgNVHQ8EBAMCAYYwQgYJYIZIAYb4QgENBDUWM1RoaXMgY2VydGlmaWNhdGUgY2Fu +bm90IGJlIHRydXN0ZWQgZm9yIGFueSBwdXJwb3NlLjAVBgNVHSAEDjAMMAoGCCsG +AQUFBw0CMAoGA1UdNgQDAgECMIGRBggrBgEFBQcBFQSBhDCBgTBZBgsqhkiG9w0B +CRAHAwMCBeAxRjBEgAsqhkiG9w0BCRAHBIE1MDMMF0xBVyBERVBBUlRNRU5UIFVT +RSBPTkxZDBhIVU1BTiBSRVNPVVJDRVMgVVNFIE9OTFkwEQYLKoZIhvcNAQkQBwID +AgTwMBEGCyqGSIb3DQEJEAcBAwIF4DAKBggqhkjOPQQDAwNnADBkAjAZSD+BVqzc +1l0fDoH3LwixjxvtddBHbJsM5yBek4U9b2yWL2KEmwV02fTgof3AjDECMCTsksmx +5f3i5DSYfe9Q1heJlEJLd1hgZmfvUYNnCU3WrdmYzyoNdNTbg7ZFMoxsXw== +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + cat_value_found = False + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5913.id_pe_clearanceConstraints: + self.assertIn(extn['extnID'], rfc5280.certificateExtensionsMap) + + ev, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertFalse(rest) + self.assertTrue(ev.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(ev)) + + for c in ev: + if c['policyId'] == rfc3114.id_tsp_TEST_Whirlpool: + for sc in c['securityCategories']: + self.assertIn(sc['type'], rfc5755.securityCategoryMap) + + scv, rest = der_decoder( + sc['value'], + asn1Spec=rfc5755.securityCategoryMap[sc['type']]) + + for cat in scv: + self.assertIn('USE ONLY', cat) + cat_value_found = True + + self.assertTrue(cat_value_found) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + cat_value_found = False + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5913.id_pe_clearanceConstraints: + self.assertIn(extn['extnID'], rfc5280.certificateExtensionsMap) + + ev, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']], + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(ev.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(ev)) + + for c in ev: + if c['policyId'] == rfc3114.id_tsp_TEST_Whirlpool: + for sc in c['securityCategories']: + self.assertIn(sc['type'], rfc5755.securityCategoryMap) + for cat in sc['value']: + self.assertIn('USE ONLY', cat) + cat_value_found = True + + self.assertTrue(cat_value_found) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc5914.py b/tests/test_rfc5914.py new file mode 100644 index 0000000..3a70ec8 --- /dev/null +++ b/tests/test_rfc5914.py @@ -0,0 +1,79 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5914 +from pyasn1_modules import rfc5652 + + +class TrustAnchorListTestCase(unittest.TestCase): + trust_anchor_list_pem_text = """\ +MIIGGQYLKoZIhvcNAQkQASKgggYIMIIGBKGCAvYwggLyoAMCAQICAgDJMA0GCSqG +SIb3DQEBCwUAMBYxFDASBgNVBAMTC3JpcGUtbmNjLXRhMCAXDTE3MTEyODE0Mzk1 +NVoYDzIxMTcxMTI4MTQzOTU1WjAWMRQwEgYDVQQDEwtyaXBlLW5jYy10YTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANFEWEhqlM9psgbDs3ltY0OjbMTb +5SzMoVpJ755fDYgQrP0/0tl7jSkDWfsAWcSIDz1dqRQRXkAL6B/1ivNx8ANuldrI +sJvzGNpymfjpcPsJac5WdadyKY9njXCq5orfAcAQvMSJs7ghmldI5EQdBmdIaB+j +JdN7pi6a0bJ+r9MTj9PpekHNWRzBVRW9/OSEOxUEE3FSMa3XjLKMiavXjJBOg6HJ +R4RfzZUpZV7mwEkPSlFqidPjrd0Al6+C1xAjH5KZFUdk2U/r+b+ufGx1bOmcUQ9W ++lJNbkCgMh1G5/7V7z/Ja4wImxs1bFw09i9MeBHcfkHYsT4Do4t4ATMi9lcCAwEA +AaOCAV4wggFaMB0GA1UdDgQWBBToVSsf1tGk9+QExtjlaA0evBY/wzAPBgNVHRMB +Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjCBsQYIKwYBBQUHAQsEgaQwgaEwPAYI +KwYBBQUHMAqGMHJzeW5jOi8vcnBraS5yaXBlLm5ldC9yZXBvc2l0b3J5L3JpcGUt +bmNjLXRhLm1mdDAyBggrBgEFBQcwDYYmaHR0cHM6Ly9ycmRwLnJpcGUubmV0L25v +dGlmaWNhdGlvbi54bWwwLQYIKwYBBQUHMAWGIXJzeW5jOi8vcnBraS5yaXBlLm5l +dC9yZXBvc2l0b3J5LzAYBgNVHSABAf8EDjAMMAoGCCsGAQUFBw4CMCcGCCsGAQUF +BwEHAQH/BBgwFjAJBAIAATADAwEAMAkEAgACMAMDAQAwIQYIKwYBBQUHAQgBAf8E +EjAQoA4wDDAKAgEAAgUA/////zCCAgIwggGIoAMCAQICCQDokdYGkU/O8jAKBggq +hkjOPQQDAzA/MQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkExEDAOBgNVBAcMB0hl +cm5kb24xETAPBgNVBAoMCEJvZ3VzIENBMB4XDTE5MDUxNDA4NTgxMVoXDTIxMDUx +MzA4NTgxMVowPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMRAwDgYDVQQHDAdI +ZXJuZG9uMREwDwYDVQQKDAhCb2d1cyBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IA +BPBRdlSx6I5qpZ2sKUMIxun1gUAzzstOYWKvKCnMoNT1x+pIKDvMEMimFcLAxxL3 +NVYOhK0Jty83SPDkKWMdx9/Okdhf3U/zxJlEnXDiFrAeM6xbG8zcCRiBnmd92Uvs +RqNQME4wHQYDVR0OBBYEFPI12zQE2qVV8r1pA5mwYuziFQjBMB8GA1UdIwQYMBaA +FPI12zQE2qVV8r1pA5mwYuziFQjBMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwMD +aAAwZQIwWlGNjb9NyqJSzUSdsEqDSvMZb8yFkxYCIbAVqQ9UqScUUb9tpJKGsPWw +bZsnLVvmAjEAt/ypozbUhQw4dSPpWzrn5BQ0kKbDM3DQJcBABEUBoIOol1/jYQPm +xajQuxcheFlkooIBADCB/TB2MBAGByqGSM49AgEGBSuBBAAiA2IABOIIQup32CTe +oCxkpBPOQJwjcqkCCg43PyE2uI1TFPbVkZVL85YCjXEexNjLp59e76Dmf1qSEZZT +b+vAyz+u/Vs/RyTnmgculr6oL7tXGK9xpL14Oh7oWzxrZBErzDQrjAQUo53mH/na +OU/AbuiRy5Wl2jHiCp8MFURpZ2lDZXJ0IFRydXN0IEFuY2hvcjBSMEwxCzAJBgNV +BAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJjAkBgNVBAMTHURpZ2lDZXJ0 +IEVDQyBTZWN1cmUgU2VydmVyIENBggIFIIICZW4= +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.trust_anchor_list_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5914.id_ct_trustAnchorList, asn1Object['contentType']) + + tal, rest = der_decoder(asn1Object['content'], rfc5914.TrustAnchorList()) + + self.assertFalse(rest) + self.assertTrue(tal.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(tal)) + self.assertEqual(3, sum(1 for _ in tal)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc5915.py b/tests/test_rfc5915.py new file mode 100644 index 0000000..6e54e5a --- /dev/null +++ b/tests/test_rfc5915.py @@ -0,0 +1,45 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5915 +from pyasn1_modules import rfc5480 + + +class MUDCertTestCase(unittest.TestCase): + private_key_pem_text = """\ +MIGkAgEBBDDLjzGbbLrR3T13lrrVum7WC/4Ua4Femc1RhhNVe1Q5XsArQ33kn9kx +3lOUfOcG+qagBwYFK4EEACKhZANiAAT4zZ8HL+xEDpXWkoWp5xFMTz4u4Ae1nF6z +XCYlmsEGD5vPu5hl9hDEjd1UHRgJIPoy3fJcWWeZ8FHCirICtuMgFisNscG/aTwK +yDYOFDuqz/C2jyEwqgWCRyxyohuJXtk= +""" + + def setUp(self): + self.asn1Spec = rfc5915.ECPrivateKey() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.private_key_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual( + rfc5480.secp384r1, asn1Object['parameters']['namedCurve']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5916.py b/tests/test_rfc5916.py new file mode 100644 index 0000000..a653b8c --- /dev/null +++ b/tests/test_rfc5916.py @@ -0,0 +1,107 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5916 + + +class DeviceCertTestCase(unittest.TestCase): + cert_pem_text = """\ +MIICpzCCAiygAwIBAgIJAKWzVCgbsG5FMAoGCCqGSM49BAMDMD8xCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9n +dXMgQ0EwHhcNMTkxMDMxMTQwMDE1WhcNMjAxMDMwMTQwMDE1WjB4MQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xEDAOBgNVBAoTB0V4 +YW1wbGUxGjAYBgNVBAsTEURldmljZSBPcGVyYXRpb25zMRwwGgYDVQQDExNleDEy +MzQ1LmV4YW1wbGUuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE7Lje3glS2qYl +5x6N9TOlD4CbnzfFeJQfbDaCa3vexEiwE0apuAP+4L5fqOsYeZC970iNW+z3PdUs +GzkKDC2cCVy8nIxQ3mWhNQDvavT3iz5OGSwa1GjSXRFbGn2x9QjNo4G6MIG3MEIG +CWCGSAGG+EIBDQQ1FjNUaGlzIGNlcnRpZmljYXRlIGNhbm5vdCBiZSB0cnVzdGVk +IGZvciBhbnkgcHVycG9zZS4wHQYDVR0OBBYEFPTQN1kXEM5Rd4hNvQL5HyA+o2No +MB8GA1UdIwQYMBaAFPI12zQE2qVV8r1pA5mwYuziFQjBMAsGA1UdDwQEAwIHgDAk +BgNVHQkEHTAbMBkGCWCGSAFlAgEFRTEMBgorBgEEAYGsYDAYMAoGCCqGSM49BAMD +A2kAMGYCMQCt6AceOEIwXFKFHIV8+wTK/vgs7ZYSA6jhXUpzNtzZw1xh9NxVUhmx +pogu5Q9Vp28CMQC5YVF8dShC1tk9YImRftiVl8C6pbj//1K/+MwmR6nRk/WU+hKl ++Qsc5Goi6At471s= +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + found_dev_owner = False + der_dev_own_oid = der_encoder(univ.ObjectIdentifier('1.3.6.1.4.1.22112.48.24')) + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectDirectoryAttributes: + self.assertIn(extn['extnID'], rfc5280.certificateExtensionsMap) + ev, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertFalse(rest) + self.assertTrue(ev.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(ev)) + + for attr in ev: + if attr['type'] == rfc5916.id_deviceOwner: + self.assertEqual(der_dev_own_oid, attr['values'][0]) + found_dev_owner = True + + self.assertTrue(found_dev_owner) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder(substrate, + asn1Spec=self.asn1Spec, + decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + found_dev_owner = False + dev_own_oid = univ.ObjectIdentifier('1.3.6.1.4.1.22112.48.24') + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectDirectoryAttributes: + self.assertIn(extn['extnID'], rfc5280.certificateExtensionsMap) + ev, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']], + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(ev.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(ev)) + + for attr in ev: + if attr['type'] == rfc5916.id_deviceOwner: + self.assertEqual(dev_own_oid, attr['values'][0]) + found_dev_owner = True + + self.assertTrue(found_dev_owner) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5917.py b/tests/test_rfc5917.py new file mode 100644 index 0000000..1023fb8 --- /dev/null +++ b/tests/test_rfc5917.py @@ -0,0 +1,119 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5917 + + +class ClearanceSponsorTestCase(unittest.TestCase): + cert_pem_text = """\ +MIID1DCCA1qgAwIBAgIUUc1IQGJpeYQ0XwOS2ZmVEb3aeZ0wCgYIKoZIzj0EAwMw +ZjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlZBMRAwDgYDVQQHEwdIZXJuZG9uMRAw +DgYDVQQKEwdFeGFtcGxlMQwwCgYDVQQLEwNQQ0ExGDAWBgNVBAMTD3BjYS5leGFt +cGxlLmNvbTAeFw0xOTExMDUyMjIwNDZaFw0yMDExMDQyMjIwNDZaMIGSMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xEDAOBgNVBAoT +B0V4YW1wbGUxIjAgBgNVBAsTGUh1bWFuIFJlc291cmNlIERlcGFydG1lbnQxDTAL +BgNVBAMTBEZyZWQxHzAdBgkqhkiG9w0BCQEWEGZyZWRAZXhhbXBsZS5jb20wdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAAQObFslQ2EBP0xlDJ3sRnsNaqm/woQgKpBispSx +XxK5bWUVpfnWsZnjLWhtDuPcu1BcBlM2g7gwL/aw8nUSIK3D8Ja9rTUQQXc3zxnk +cl8+8znNXHMGByRjPUH87C+TOrqjggGaMIIBljAdBgNVHQ4EFgQU5m711OqFDNGR +SWMOSzTXjpTLIFUwbwYDVR0jBGgwZoAUJuolDwsyICik11oKjf8t3L1/VGWhQ6RB +MD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjER +MA8GA1UECgwIQm9ndXMgQ0GCCQCls1QoG7BuRjAPBgNVHRMBAf8EBTADAQH/MAsG +A1UdDwQEAwIBhjBCBglghkgBhvhCAQ0ENRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5u +b3QgYmUgdHJ1c3RlZCBmb3IgYW55IHB1cnBvc2UuMBUGA1UdIAQOMAwwCgYIKwYB +BQUHDQIwCgYDVR02BAMCAQIwfwYDVR0JBHgwdjBJBgNVBDcxQjBABgsqhkiG9w0B +CRAHAwMCBeAxLTArgAsqhkiG9w0BCRAHBIEcMBoMGEhVTUFOIFJFU09VUkNFUyBV +U0UgT05MWTApBglghkgBZQIBBUQxHAwaSHVtYW4gUmVzb3VyY2VzIERlcGFydG1l +bnQwCgYIKoZIzj0EAwMDaAAwZQIwVh/RypULFgPpAN0I7OvuMomRWnm/Hea3Hk8P +tTRz2Zai8iYat7oeAmGVgMhSXy2jAjEAuJW4l/CFatBy4W/lZ7gS3weBdBa5WEDI +FFMC7GjGtCeLtXYqWfBnRdK26dOaHLB2 +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + cs = rfc5917.DirectoryString() + cs['utf8String'] = u'Human Resources Department' + encoded_cs = der_encoder(cs) + + clearance_sponsor_found = False + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectDirectoryAttributes: + + self.assertIn(extn['extnID'], rfc5280.certificateExtensionsMap) + + ev, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertFalse(rest) + self.assertTrue(ev.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(ev)) + + for attr in ev: + if attr['type'] == rfc5917.id_clearanceSponsor: + self.assertEqual(encoded_cs, attr['values'][0]) + clearance_sponsor_found = True + + self.assertTrue(clearance_sponsor_found) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + clearance_sponsor_found = False + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectDirectoryAttributes: + self.assertIn(extn['extnID'], rfc5280.certificateExtensionsMap) + + ev, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']], + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(ev.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(ev)) + + for attr in ev: + if attr['type'] == rfc5917.id_clearanceSponsor: + hrd = u'Human Resources Department' + + self.assertEqual(hrd, attr['values'][0]['utf8String']) + + clearance_sponsor_found = True + + self.assertTrue(clearance_sponsor_found) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc5924.py b/tests/test_rfc5924.py new file mode 100644 index 0000000..f1ae64a --- /dev/null +++ b/tests/test_rfc5924.py @@ -0,0 +1,74 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5924 + + +class SIPDomainCertTestCase(unittest.TestCase): + cert_pem_text = """\ +MIICiTCCAg+gAwIBAgIJAKWzVCgbsG5EMAoGCCqGSM49BAMDMD8xCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9n +dXMgQ0EwHhcNMTkxMDMwMjEwMDM0WhcNMjAxMDI5MjEwMDM0WjBsMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xEDAOBgNVBAoTB0V4 +YW1wbGUxEjAQBgNVBAsTCVNJUCBQcm94eTEYMBYGA1UEAxMPc2lwLmV4YW1wbGUu +Y29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEcY3ckttSa6z3CfOFwZvPmZY8C9Ml +D1XOydz00+Vqifh1lydhDuulHrJaQ+QgVjG1TzlTAssD9GeABit/M98DPS/IC3wi +TsTMSyQ9/Oz4hKAw7x7lYEvufvycsZ7pJGRso4GpMIGmMEIGCWCGSAGG+EIBDQQ1 +FjNUaGlzIGNlcnRpZmljYXRlIGNhbm5vdCBiZSB0cnVzdGVkIGZvciBhbnkgcHVy +cG9zZS4wHQYDVR0OBBYEFEcJ8iFWmJOl3Hg/44UFgFWNbe7FMB8GA1UdIwQYMBaA +FPI12zQE2qVV8r1pA5mwYuziFQjBMAsGA1UdDwQEAwIHgDATBgNVHSUEDDAKBggr +BgEFBQcDFDAKBggqhkjOPQQDAwNoADBlAjAXEPPNyXBUj40dzy+ZOqafuM3/6Fy6 +bkgiIObcQImra96X10fe6qacanrbu4uU6d8CMQCQ+BCjCnOP4dBbNC3vB0WypxLo +UwZ6TjS0Rfr+dRvlyilVjP+hPVwbyb7ZOSZR6zk= +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + found_kp_sipDomain = False + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_extKeyUsage: + self.assertIn( + extn['extnID'], rfc5280.certificateExtensionsMap) + + ev, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertFalse(rest) + self.assertTrue(ev.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(ev)) + self.assertIn(rfc5924.id_kp_sipDomain, ev) + + found_kp_sipDomain = True + + self.assertTrue(found_kp_sipDomain) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5934.py b/tests/test_rfc5934.py new file mode 100644 index 0000000..ba18b56 --- /dev/null +++ b/tests/test_rfc5934.py @@ -0,0 +1,299 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley +# Acknowledgement to Carl Wallace for the test messages. +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5934 + + +class TAMPStatusResponseTestCase(unittest.TestCase): + tsr_pem_text = """\ +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 +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.tsr_pem_text) + + layers = { + rfc5652.id_ct_contentInfo: rfc5652.ContentInfo(), + rfc5652.id_signedData: rfc5652.SignedData(), + rfc5934.id_ct_TAMP_statusResponse: rfc5934.TAMPStatusResponse() + } + + getNextLayer = { + rfc5652.id_ct_contentInfo: lambda x: x['contentType'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContentType'], + rfc5934.id_ct_TAMP_statusResponse: lambda x: None + } + + getNextSubstrate = { + rfc5652.id_ct_contentInfo: lambda x: x['content'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContent'], + rfc5934.id_ct_TAMP_statusResponse: lambda x: None + } + + next_layer = rfc5652.id_ct_contentInfo + + while next_layer: + asn1Object, rest = der_decoder(substrate, asn1Spec=layers[next_layer]) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + substrate = getNextSubstrate[next_layer](asn1Object) + next_layer = getNextLayer[next_layer](asn1Object) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.tsr_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=rfc5652.ContentInfo(), decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + eci = asn1Object['content']['encapContentInfo'] + + self.assertIn(eci['eContentType'], rfc5652.cmsContentTypesMap) + self.assertEqual(rfc5934.id_ct_TAMP_statusResponse, eci['eContentType']) + + tsr, rest = der_decoder( + eci['eContent'], + asn1Spec=rfc5652.cmsContentTypesMap[eci['eContentType']], + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(tsr.prettyPrint()) + self.assertEqual(eci['eContent'], der_encoder(tsr)) + self.assertEqual(2, tsr['version']) + self.assertEqual(univ.Null(""), tsr['query']['target']) + self.assertEqual(1568307071, tsr['query']['seqNum']) + self.assertFalse(tsr['usesApex']) + + count = 0 + + for tai in tsr['response']['verboseResponse']['taInfo']: + count += 1 + self.assertEqual(1, tai['taInfo']['version']) + + self.assertEqual(3, count) + + +class TrustAnchorUpdateTestCase(unittest.TestCase): + tau_pem_text = """\ +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""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.tau_pem_text) + + layers = { + rfc5652.id_ct_contentInfo: rfc5652.ContentInfo(), + rfc5652.id_signedData: rfc5652.SignedData(), + rfc5934.id_ct_TAMP_update: rfc5934.TAMPUpdate() + } + + getNextLayer = { + rfc5652.id_ct_contentInfo: lambda x: x['contentType'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContentType'], + rfc5934.id_ct_TAMP_update: lambda x: None + } + + getNextSubstrate = { + rfc5652.id_ct_contentInfo: lambda x: x['content'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContent'], + rfc5934.id_ct_TAMP_update: lambda x: None + } + + next_layer = rfc5652.id_ct_contentInfo + + while next_layer: + asn1Object, rest = der_decoder(substrate, asn1Spec=layers[next_layer]) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + substrate = getNextSubstrate[next_layer](asn1Object) + next_layer = getNextLayer[next_layer](asn1Object) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.tau_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=rfc5652.ContentInfo(), + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + eci = asn1Object['content']['encapContentInfo'] + self.assertIn(eci['eContentType'], rfc5652.cmsContentTypesMap) + self.assertEqual(rfc5934.id_ct_TAMP_update, eci['eContentType']) + + tau, rest = der_decoder( + eci['eContent'], + asn1Spec=rfc5652.cmsContentTypesMap[eci['eContentType']], + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(tau.prettyPrint()) + self.assertEqual(eci['eContent'], der_encoder(tau)) + self.assertEqual(2, tau['version']) + self.assertEqual(univ.Null(""), tau['msgRef']['target']) + self.assertEqual(1568307088, tau['msgRef']['seqNum']) + self.assertEqual(1, len(tau['updates'])) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5940.py b/tests/test_rfc5940.py new file mode 100644 index 0000000..d55ba6e --- /dev/null +++ b/tests/test_rfc5940.py @@ -0,0 +1,141 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc2560 +from pyasn1_modules import rfc5940 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5280 + + +class CRLandOCSPResponseTestCase(unittest.TestCase): + pem_text = """\ +MIIHWQYJKoZIhvcNAQcCoIIHSjCCB0YCAQExDTALBglghkgBZQMEAgEwUwYJKoZI +hvcNAQcBoEYERENvbnRlbnQtVHlwZTogdGV4dC9wbGFpbg0KDQpXYXRzb24sIGNv +bWUgaGVyZSAtIEkgd2FudCB0byBzZWUgeW91Lg0KoIIBaDCCAWQwggEKoAMCAQIC +CQClWUKCJkwnGTAKBggqhkjOPQQDAjAkMRQwEgYDVQQKDAtleGFtcGxlLm9yZzEM +MAoGA1UEAwwDQm9iMB4XDTE3MTIyMDIzMDc0OVoXDTE4MTIyMDIzMDc0OVowJDEU +MBIGA1UECgwLZXhhbXBsZS5vcmcxDDAKBgNVBAMMA0JvYjBZMBMGByqGSM49AgEG +CCqGSM49AwEHA0IABIZP//xT8ah2ymmxfidIegeccVKuGxN+OTuvGq69EnQ8fUFD +ov2KNw8Cup0DtzAfHaZOMFWUu2+Vy3H6SLbQo4OjJTAjMCEGA1UdEQEB/wQXMBWG +E3NpcDpib2JAZXhhbXBsZS5vcmcwCgYIKoZIzj0EAwIDSAAwRQIhALIkjJJAKCI4 +nsklf2TM/RBvuguWwRkHMDTVGxAvczlsAiAVjrFR8IW5vS4EzyePDVIua7b+Tzb3 +THcQsVpPR53kDaGCBGQwggIbMIIBAwIBATANBgkqhkiG9w0BAQsFADBsMQswCQYD +VQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGln +aWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBS +b290IENBFw0xOTA1MDIyMjE1NTRaFw0xOTA1MjMyMjE1NTRaMDEwLwIQDPWCOBgZ +nlb4K9ZS7Sft6RcNMTgxMDI1MTYxMTM4WjAMMAoGA1UdFQQDCgEAoDAwLjAfBgNV +HSMEGDAWgBSxPsNpA/i/RwHUmCYaCALvY2QrwzALBgNVHRQEBAICAcQwDQYJKoZI +hvcNAQELBQADggEBABPO3OA0OkQZ+RLVxz/cNx5uNVEO416oOePkN0A4DxFztf33 +7caS4OyfS9Wyu1j5yUdWJVpAKXSQeN95MqHkpSpYDssuqbuYjv8ViJfseGBgtXTc +zUzzNeNdY2uxMbCxuhmPkgacAo1lx9LkK2ScYHWVbfFRF1UQ/dcmavaZsEOBNuLW +OxQYA9MqfVNAymHe7vPqwm/8IY2FbHe9HsiJZfGxNWMDP5lmJiXmpntTeDQ2Ujdi +yXwGGKjyiSTFk2jVRutrGINufaoA/f7eCmIb4UDPbpMjVfD215dW8eBKouypCVoE +vmCSSTacdiBI2yOluvMN0PzvPve0ECAE+D4em9ahggJBBggrBgEFBQcQAjCCAjMK +AQCgggIsMIICKAYJKwYBBQUHMAEBBIICGTCCAhUwZqEgMB4xHDAJBgNVBAYTAlJV +MA8GA1UEAx4IAFQAZQBzAHQYEzIwMTkwNTA5MTU1MDQ4LjI1OVowLTArMBIwBwYF +Kw4DAhoEAQEEAQECAQGAABgTMjAxOTA1MDkxNTUwNDguMjYxWjAKBggqhkjOPQQD +AgNJADBGAiEAujFVH+NvuTLYa8RW3pvWSUwZfjOW5H5171JI+/50BjcCIQDhwige +wl+ts6TIvhU+CFoOipQBNKyKXKh7ngJkUtpZ86CCAVIwggFOMIIBSjCB8aADAgEC +AgEBMAoGCCqGSM49BAMCMB4xHDAJBgNVBAYTAlJVMA8GA1UEAx4IAFQAZQBzAHQw +HhcNMTkwMjAxMDUwMDAwWhcNMjIwMjAxMDUwMDAwWjAeMRwwCQYDVQQGEwJSVTAP +BgNVBAMeCABUAGUAcwB0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEM0jxEYgg +RxC/r87uV/h6iZ8BAdHT/6fxRuzG0PRMIlFBy38skFUXJJulKV9JW16YJqOkVsqv +xwMM61z7p1vQ/qMgMB4wDwYDVR0TBAgwBgEB/wIBAzALBgNVHQ8EBAMCAAYwCgYI +KoZIzj0EAwIDSAAwRQIhAIdpCt5g89ofSADXmBD3KXQGnTghwbAMeWrKXqTGww+x +AiAl8NQgfUk4xMymZ3VtCLJ2MdczDps4Zh2KPOqAR5fZAjGCAQcwggEDAgEBMDEw +JDEUMBIGA1UECgwLZXhhbXBsZS5vcmcxDDAKBgNVBAMMA0JvYgIJAKVZQoImTCcZ +MAsGCWCGSAFlAwQCAaBpMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZI +hvcNAQkFMQ8XDTE5MDEyNDIzNTI1NlowLwYJKoZIhvcNAQkEMSIEIO93j8lA1ebc +JXb0elmbMSYZWp8aInra81+iLAUNjRlaMAoGCCqGSM49BAMCBEcwRQIhAPeI7URq +tw//LB/6TAN0/Qh3/WHukXwxRbOJpnYVx0b6AiB3lK3FfwBhx4S5YSPMblS7goJl +ttTMEpl2prH8bbwo1g== +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + sd, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.SignedData()) + + self.assertTrue(sd.prettyPrint()) + + self.assertEqual( + rfc5652.id_data, sd['encapContentInfo']['eContentType']) + self.assertTrue(sd['encapContentInfo']['eContent']) + + v2 = rfc5280.Version(value='v2') + + self.assertEqual(v2, sd['crls'][0]['crl']['tbsCertList']['version']) + + ocspr_oid = rfc5940.id_ri_ocsp_response + + self.assertEqual(ocspr_oid, sd['crls'][1]['other']['otherRevInfoFormat']) + + ocspr, rest = der_decoder( + sd['crls'][1]['other']['otherRevInfo'], + asn1Spec=rfc5940.OCSPResponse()) + + self.assertTrue(ocspr.prettyPrint()) + + success = rfc2560.OCSPResponseStatus(value='successful') + + self.assertEqual(success, ocspr['responseStatus']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + sd_eci = asn1Object['content']['encapContentInfo'] + + self.assertEqual(rfc5652.id_data, sd_eci['eContentType']) + self.assertTrue(sd_eci['eContent'].hasValue()) + + for ri in asn1Object['content']['crls']: + if ri.getName() == 'crl': + v2 = rfc5280.Version(value='v2') + self.assertEqual(v2, ri['crl']['tbsCertList']['version']) + + if ri.getName() == 'other': + ori = ri['other'] + ocspr_oid = rfc5940.id_ri_ocsp_response + + self.assertEqual(ocspr_oid, ori['otherRevInfoFormat']) + + ocspr_status = ori['otherRevInfo']['responseStatus'] + success = rfc2560.OCSPResponseStatus(value='successful') + + self.assertEqual(success, ocspr_status) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5958.py b/tests/test_rfc5958.py new file mode 100644 index 0000000..980a11e --- /dev/null +++ b/tests/test_rfc5958.py @@ -0,0 +1,84 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5958 +from pyasn1_modules import rfc8410 + + +class PrivateKeyTestCase(unittest.TestCase): + priv_key_pem_text = """\ +MHICAQEwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwoy/HU++CXqI9EdVhC +oB8wHQYKKoZIhvcNAQkJFDEPDA1DdXJkbGUgQ2hhaXJzgSEAGb9ECWmEzf6FQbrB +Z9w7lshQhqowtrbLDFw4rXAxZuE= +""" + + def setUp(self): + self.asn1Spec = rfc5958.PrivateKeyInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.priv_key_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual( + rfc8410.id_Ed25519, asn1Object['privateKeyAlgorithm']['algorithm']) + self.assertTrue(asn1Object['privateKey'].isValue) + self.assertEqual( + "0x0420d4ee", asn1Object['privateKey'].prettyPrint()[0:10]) + self.assertTrue(asn1Object['publicKey'].isValue) + self.assertEqual( + "1164575857", asn1Object['publicKey'].prettyPrint()[0:10]) + self.assertEqual(substrate, der_encoder(asn1Object)) + + +class PrivateKeyOpenTypesTestCase(unittest.TestCase): + asymmetric_key_pkg_pem_text = """\ +MIGEBgpghkgBZQIBAk4FoHYwdDByAgEBMAUGAytlcAQiBCDU7nLb+RNYStW22PH3 +afitOv58KMvx1Pvgl6iPRHVYQqAfMB0GCiqGSIb3DQEJCRQxDwwNQ3VyZGxlIENo +YWlyc4EhABm/RAlphM3+hUG6wWfcO5bIUIaqMLa2ywxcOK1wMWbh +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.asymmetric_key_pkg_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertIn( + rfc5958.id_ct_KP_aKeyPackage, rfc5652.cmsContentTypesMap) + + oneKey = asn1Object['content'][0] + + self.assertEqual( + rfc8410.id_Ed25519, oneKey['privateKeyAlgorithm']['algorithm']) + + pkcs_9_at_friendlyName = univ.ObjectIdentifier('1.2.840.113549.1.9.9.20') + + self.assertEqual( + pkcs_9_at_friendlyName, oneKey['attributes'][0]['attrType']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc5990.py b/tests/test_rfc5990.py new file mode 100755 index 0000000..7d51d67 --- /dev/null +++ b/tests/test_rfc5990.py @@ -0,0 +1,87 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5990 + + +class RSAKEMTestCase(unittest.TestCase): + pem_text = """\ +MEcGCyqGSIb3DQEJEAMOMDgwKQYHKIGMcQICBDAeMBkGCiuBBRCGSAksAQIwCwYJ +YIZIAWUDBAIBAgEQMAsGCWCGSAFlAwQBBQ== +""" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5990.id_rsa_kem, asn1Object['algorithm']) + + rsa_kem_p, rest = der_decoder( + asn1Object['parameters'], + asn1Spec=rfc5280.algorithmIdentifierMap[rfc5990.id_rsa_kem]) + + self.assertFalse(rest) + self.assertTrue(rsa_kem_p.prettyPrint()) + self.assertEqual(asn1Object['parameters'], der_encoder(rsa_kem_p)) + self.assertEqual(rfc5990.id_kem_rsa, rsa_kem_p['kem']['algorithm']) + + kem_rsa_p, rest = der_decoder( + rsa_kem_p['kem']['parameters'], + asn1Spec=rfc5280.algorithmIdentifierMap[rfc5990.id_kem_rsa]) + + self.assertFalse(rest) + self.assertTrue(kem_rsa_p.prettyPrint()) + self.assertEqual( + rsa_kem_p['kem']['parameters'], der_encoder(kem_rsa_p)) + self.assertEqual(16, kem_rsa_p['keyLength']) + self.assertEqual( + rfc5990.id_kdf_kdf3, kem_rsa_p['keyDerivationFunction']['algorithm']) + + kdf_p, rest = der_decoder( + kem_rsa_p['keyDerivationFunction']['parameters'], + asn1Spec=rfc5280.algorithmIdentifierMap[rfc5990.id_kdf_kdf3]) + + self.assertFalse(rest) + self.assertTrue(kdf_p.prettyPrint()) + self.assertEqual( + kem_rsa_p['keyDerivationFunction']['parameters'], + der_encoder(kdf_p)) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5990.id_rsa_kem, asn1Object['algorithm']) + self.assertEqual( + rfc5990.id_kem_rsa, asn1Object['parameters']['kem']['algorithm']) + self.assertEqual( + 16, asn1Object['parameters']['kem']['parameters']['keyLength']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc6010.py b/tests/test_rfc6010.py new file mode 100644 index 0000000..1726a8d --- /dev/null +++ b/tests/test_rfc6010.py @@ -0,0 +1,101 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc6010 + + +class UnconstrainedCCCExtensionTestCase(unittest.TestCase): + unconstrained_pem_text = "MB0GCCsGAQUFBwESBBEwDzANBgsqhkiG9w0BCRABAA==" + + def setUp(self): + self.asn1Spec = rfc5280.Extension() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.unconstrained_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual( + rfc6010.id_pe_cmsContentConstraints, asn1Object['extnID']) + + evalue, rest = der_decoder( + asn1Object['extnValue'], + asn1Spec=rfc6010.CMSContentConstraints()) + + self.assertFalse(rest) + self.assertTrue(evalue.prettyPrint()) + self.assertEqual(asn1Object['extnValue'], der_encoder(evalue)) + self.assertEqual( + rfc6010.id_ct_anyContentType, evalue[0]['contentType']) + + +class ConstrainedCCCExtensionTestCase(unittest.TestCase): + constrained_pem_text = """\ +MIG7BggrBgEFBQcBEgSBrjCBqzA0BgsqhkiG9w0BCRABEDAlMCMGCyqGSIb3DQEJ +EAwBMRQMElZpZ2lsIFNlY3VyaXR5IExMQzAwBgpghkgBZQIBAk4CMCIwIAYLKoZI +hvcNAQkQDAsxEQwPa3RhLmV4YW1wbGUuY29tMDEGCyqGSIb3DQEJEAEZMCIwIAYL +KoZIhvcNAQkQDAsxEQwPa3RhLmV4YW1wbGUuY29tMA4GCSqGSIb3DQEHAQoBAQ== +""" + + def setUp(self): + self.asn1Spec = rfc5280.Extension() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.constrained_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual( + rfc6010.id_pe_cmsContentConstraints, asn1Object['extnID']) + + evalue, rest = der_decoder( + asn1Object['extnValue'], + asn1Spec=rfc6010.CMSContentConstraints()) + + self.assertFalse(rest) + self.assertTrue(evalue.prettyPrint()) + self.assertEqual(asn1Object['extnValue'], der_encoder(evalue)) + + constraint_count = 0 + attribute_count = 0 + cannot_count = 0 + + for ccc in evalue: + constraint_count += 1 + if ccc['canSource'] == 1: + cannot_count += 1 + if ccc['attrConstraints'].hasValue(): + for attr in ccc['attrConstraints']: + attribute_count += 1 + + self.assertEqual(4, constraint_count) + self.assertEqual(3, attribute_count) + self.assertEqual(1, cannot_count) + + def testExtensionsMap(self): + substrate = pem.readBase64fromText(self.constrained_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertIn(asn1Object['extnID'], rfc5280.certificateExtensionsMap) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc6019.py b/tests/test_rfc6019.py new file mode 100644 index 0000000..2e08670 --- /dev/null +++ b/tests/test_rfc6019.py @@ -0,0 +1,56 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc6019 + + +class BinarySigningTimeTestCase(unittest.TestCase): + pem_text = "MBUGCyqGSIb3DQEJEAIuMQYCBFy/hlQ=" + + def setUp(self): + self.asn1Spec = rfc5652.Attribute() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc6019.id_aa_binarySigningTime, asn1Object['attrType']) + + bintime, rest = der_decoder( + asn1Object['attrValues'][0], asn1Spec=rfc6019.BinaryTime()) + + self.assertEqual(0x5cbf8654, bintime) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertIn(asn1Object['attrType'], rfc5652.cmsAttributesMap) + self.assertEqual(0x5cbf8654, asn1Object['attrValues'][0]) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc6031.py b/tests/test_rfc6031.py new file mode 100644 index 0000000..29a8d86 --- /dev/null +++ b/tests/test_rfc6031.py @@ -0,0 +1,91 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc6031 + + +class SymmetricKeyPkgTestCase(unittest.TestCase): + key_pkg_pem_text = """\ +MIG7BgsqhkiG9w0BCRABGaCBqzCBqKBEMCMGCyqGSIb3DQEJEAwBMRQMElZpZ2ls +IFNlY3VyaXR5IExMQzAdBgsqhkiG9w0BCRAMAzEODAxQcmV0ZW5kIDA0OEEwYDBe +MFYwGwYLKoZIhvcNAQkQDBsxDAwKZXhhbXBsZUlEMTAVBgsqhkiG9w0BCRAMCjEG +DARIT1RQMCAGCyqGSIb3DQEJEAwLMREMD2t0YS5leGFtcGxlLmNvbQQEMTIzNA== +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.key_pkg_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertIn(asn1Object['contentType'], rfc5652.cmsContentTypesMap) + + asn1Spec = rfc5652.cmsContentTypesMap[asn1Object['contentType']] + skp, rest = der_decoder(asn1Object['content'], asn1Spec=asn1Spec) + + self.assertFalse(rest) + self.assertTrue(skp.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(skp)) + + for attr in skp['sKeyPkgAttrs']: + self.assertIn(attr['attrType'], rfc6031.sKeyPkgAttributesMap) + + for osk in skp['sKeys']: + for attr in osk['sKeyAttrs']: + self.assertIn(attr['attrType'], rfc6031.sKeyAttributesMap) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.key_pkg_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertIn(asn1Object['contentType'], rfc5652.cmsContentTypesMap) + self.assertTrue(asn1Object['content'].hasValue()) + + keypkg = asn1Object['content'] + + self.assertEqual( + rfc6031.KeyPkgVersion().subtype(value='v1'), keypkg['version']) + + for attr in keypkg['sKeyPkgAttrs']: + self.assertIn(attr['attrType'], rfc6031.sKeyPkgAttributesMap) + self.assertNotEqual('0x', attr['attrValues'][0].prettyPrint()[:2]) + + # decodeOpenTypes=True did not decode if the value is shown in hex ... + if attr['attrType'] == rfc6031.id_pskc_manufacturer: + attr['attrValues'][0] == 'Vigil Security LLC' + + for osk in keypkg['sKeys']: + for attr in osk['sKeyAttrs']: + self.assertIn(attr['attrType'], rfc6031.sKeyAttributesMap) + self.assertNotEqual( + '0x', attr['attrValues'][0].prettyPrint()[:2]) + + # decodeOpenTypes=True did not decode if the value is shown in hex ... + if attr['attrType'] == rfc6031.id_pskc_issuer: + attr['attrValues'][0] == 'kta.example.com' + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc6032.py b/tests/test_rfc6032.py new file mode 100644 index 0000000..287bad8 --- /dev/null +++ b/tests/test_rfc6032.py @@ -0,0 +1,96 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.compat.octets import str2octs + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc6032 + + +class EncryptedKeyPkgTestCase(unittest.TestCase): + encrypted_key_pkg_pem_text = """\ +MIIBBwYKYIZIAWUCAQJOAqCB+DCB9QIBAjCBzgYKYIZIAWUCAQJOAjAdBglghkgB +ZQMEASoEEN6HFteHMZ3DyeO35xIwWQOAgaCKTs0D0HguNzMhsLgiwG/Kw8OwX+GF +9/cZ1YVNesUTW/VsbXJcbTmFmWyfqZsM4DLBegIbrUEHQZnQRq6/NO4ricQdHApD +B/ip6RRqeN1yxMJLv1YN0zUOOIDBS2iMEjTLXZLWw3w22GN2JK7G+Lr4OH1NhMgU +ILJyh/RePmPseMwxvcJs7liEfkiSNMtDfEcpjtzA9bDe95GjhQRsiSByoR8wHQYJ +YIZIAWUCAQVCMRAEDnB0Zi1rZGMtODEyMzc0 +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.encrypted_key_pkg_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual( + rfc6032.id_ct_KP_encryptedKeyPkg, asn1Object['contentType']) + + content, rest = der_decoder( + asn1Object['content'], rfc6032.EncryptedKeyPackage()) + + self.assertFalse(rest) + self.assertTrue(content.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(content)) + self.assertEqual('encrypted', content.getName()) + + eci = content['encrypted']['encryptedContentInfo'] + + self.assertEqual( + rfc6032.id_ct_KP_encryptedKeyPkg, eci['contentType']) + + attrType = content['encrypted']['unprotectedAttrs'][0]['attrType'] + + self.assertEqual(rfc6032.id_aa_KP_contentDecryptKeyID, attrType) + + attrVal0 = content['encrypted']['unprotectedAttrs'][0]['attrValues'][0] + keyid, rest = der_decoder(attrVal0, rfc6032.ContentDecryptKeyID()) + + self.assertFalse(rest) + self.assertTrue(keyid.prettyPrint()) + self.assertEqual(attrVal0, der_encoder(keyid)) + self.assertEqual(str2octs('ptf-kdc-812374'), keyid) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.encrypted_key_pkg_pem_text) + asn1Object, rest = der_decoder(substrate, + asn1Spec=self.asn1Spec, + decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertIn(asn1Object['contentType'], rfc5652.cmsContentTypesMap) + + eci = asn1Object['content']['encrypted']['encryptedContentInfo'] + + self.assertIn(eci['contentType'], rfc5652.cmsContentTypesMap) + + for attr in asn1Object['content']['encrypted']['unprotectedAttrs']: + self.assertIn(attr['attrType'], rfc5652.cmsAttributesMap) + self.assertNotEqual('0x', attr['attrValues'][0].prettyPrint()[:2]) + + if attr['attrType'] == rfc6032.id_aa_KP_contentDecryptKeyID: + self.assertEqual(str2octs( + 'ptf-kdc-812374'), attr['attrValues'][0]) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc6120.py b/tests/test_rfc6120.py new file mode 100644 index 0000000..bdedab8 --- /dev/null +++ b/tests/test_rfc6120.py @@ -0,0 +1,115 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.compat.octets import str2octs + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc6120 + + +class XMPPCertificateTestCase(unittest.TestCase): + xmpp_server_cert_pem_text = """\ +MIIC6DCCAm+gAwIBAgIJAKWzVCgbsG5DMAoGCCqGSM49BAMDMD8xCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9n +dXMgQ0EwHhcNMTkxMDI0MjMxNjA0WhcNMjAxMDIzMjMxNjA0WjBNMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xHzAdBgNVBAoTFkV4 +YW1wbGUgUHJvZHVjdHMsIEluYy4wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQZzQlk +03nJRPF6+w1NxFELmQ5vJTjTRz3eu03CRtahK4Wnwd4GwbDe8NVHAEG2qTzBXFDu +p6RZugsBdf9GcEZHG42rThYYOzIYzVFnI7tQgA+nTWSWZN6eoU/EXcknhgijggEn +MIIBIzAdBgNVHQ4EFgQUkQpUMYcbUesEn5buI03POFnktJgwHwYDVR0jBBgwFoAU +8jXbNATapVXyvWkDmbBi7OIVCMEwCwYDVR0PBAQDAgeAMIGPBgNVHREEgYcwgYSg +KQYIKwYBBQUHCAegHRYbX3htcHAtY2xpZW50LmltLmV4YW1wbGUuY29toCkGCCsG +AQUFBwgHoB0WG194bXBwLXNlcnZlci5pbS5leGFtcGxlLmNvbaAcBggrBgEFBQcI +BaAQDA5pbS5leGFtcGxlLmNvbYIOaW0uZXhhbXBsZS5jb20wQgYJYIZIAYb4QgEN +BDUWM1RoaXMgY2VydGlmaWNhdGUgY2Fubm90IGJlIHRydXN0ZWQgZm9yIGFueSBw +dXJwb3NlLjAKBggqhkjOPQQDAwNnADBkAjAEo4mhDGC6/R39HyNgzLseNAp36qBH +yQJ/AWsBojN0av8akeVv9IuM45yqLKdiCzcCMDCjh1lFnCvurahwp5D1j9pAZMsg +nOzhcMpnHs2U/eN0lHl/JNgnbftl6Dvnt59xdA== +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.xmpp_server_cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + count = 0 + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectAltName: + extnValue, rest = der_decoder( + extn['extnValue'], asn1Spec=rfc5280.SubjectAltName()) + + self.assertFalse(rest) + self.assertTrue(extnValue.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + for gn in extnValue: + if gn['otherName'].hasValue(): + gn_on = gn['otherName'] + if gn_on['type-id'] == rfc6120.id_on_xmppAddr: + self.assertIn(gn_on['type-id'], rfc5280.anotherNameMap) + + spec = rfc5280.anotherNameMap[gn['otherName']['type-id']] + on, rest = der_decoder(gn_on['value'], asn1Spec=spec) + + self.assertFalse(rest) + self.assertTrue(on.prettyPrint()) + self.assertEqual(gn_on['value'], der_encoder(on)) + self.assertEqual('im.example.com', on) + + count += 1 + + self.assertEqual(1, count) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.xmpp_server_cert_pem_text) + asn1Object, rest = der_decoder(substrate, + asn1Spec=self.asn1Spec, + decodeOpenTypes=True) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + count = 0 + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectAltName: + extnValue, rest = der_decoder( + extn['extnValue'], asn1Spec=rfc5280.SubjectAltName(), + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(extnValue.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + for gn in extnValue: + if gn['otherName'].hasValue(): + if gn['otherName']['type-id'] == rfc6120.id_on_xmppAddr: + self.assertEqual( + 'im.example.com', gn['otherName']['value']) + count += 1 + + self.assertEqual(1, count) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc6187.py b/tests/test_rfc6187.py new file mode 100644 index 0000000..75c1e91 --- /dev/null +++ b/tests/test_rfc6187.py @@ -0,0 +1,70 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc6187 + + +class SSHClientCertificateTestCase(unittest.TestCase): + cert_pem_text = """\ +MIICkDCCAhegAwIBAgIJAKWzVCgbsG5BMAoGCCqGSM49BAMDMD8xCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9n +dXMgQ0EwHhcNMTkxMDI0MTgyNjA3WhcNMjAxMDIzMTgyNjA3WjB0MQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xEDAOBgNVBAoTB0V4 +YW1wbGUxEDAOBgNVBAMTB0NoYXJsaWUxIjAgBgkqhkiG9w0BCQEWE2NoYXJsaWVA +ZXhhbXBsZS5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARfr1XPl5S0A/BwTOm4 +/rO7mGVt2Tmfr3yvYnfN/ggMvyS3RiIXSsdzcAwzeqc907Jp7Dggab0PpaOKDOxD +WoK0g6B8+kC/VMsU23mfShlb9et8qcR3A8gdU6g8uvSMahWjgakwgaYwCwYDVR0P +BAQDAgeAMB0GA1UdDgQWBBQfwm5u0GoxiDcjhDt33UJYlvMPFTAfBgNVHSMEGDAW +gBTyNds0BNqlVfK9aQOZsGLs4hUIwTATBgNVHSUEDDAKBggrBgEFBQcDFTBCBglg +hkgBhvhCAQ0ENRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUgdHJ1c3RlZCBm +b3IgYW55IHB1cnBvc2UuMAoGCCqGSM49BAMDA2cAMGQCMGEme38A3k8q4RGSEs2D +ThQQOQz3TBJrIW8zr92S8e8BNPkRcQDR+C72TEhL/qoPCQIwGpGaC4ERiUypETkC +voNP0ODFhhlpFo6lwVHd8Gu+6hShC2PKdAfs4QFDS9ZKgQeZ +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + ssh_eku_oids = [ + rfc6187.id_kp_secureShellClient, + rfc6187.id_kp_secureShellServer, + ] + + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + count = 0 + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_extKeyUsage: + extnValue, rest = der_decoder( + extn['extnValue'], asn1Spec=rfc5280.ExtKeyUsageSyntax()) + + for oid in extnValue: + if oid in ssh_eku_oids: + count += 1 + + self.assertEqual(1, count) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc6210.py b/tests/test_rfc6210.py new file mode 100644 index 0000000..54d8b66 --- /dev/null +++ b/tests/test_rfc6210.py @@ -0,0 +1,73 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc6210 + + +class AuthenticatedDataTestCase(unittest.TestCase): + pem_text = """\ +MIICRQYLKoZIhvcNAQkQAQKgggI0MIICMAIBADGBwDCBvQIBADAmMBIxEDAOBgNVBAMMB0 +NhcmxSU0ECEEY0a8eAAFa8EdNuLs1dcdAwDQYJKoZIhvcNAQEBBQAEgYCH70EpEikY7deb +859YJRAWfFondQv1D4NFltw6C1ceheWnlAU0C2WEXr3LUBXZp1/PSte29FnJxu5bXCTn1g +elMm6zNlZNWNd0KadVBcaxi1n8L52tVM5sWFGJPO5cStOyAka2ucuZM6iAnCSkn1Ju7fgU +5j2g3bZ/IM8nHTcygjAKBggrBgEFBQgBAqFPBgsqhkiG9w0BCRADDQRAAQIDBAUGBwgJCg +sMDQ4PEBESEwQVFhcYGRobHB0eHyAhIiMEJSYnKCkqKywtLi8wMTIzBDU2Nzg5Ojs8PT4/ +QDArBgkqhkiG9w0BBwGgHgQcVGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50LqKBxzAYBg +kqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wOTEyMTAyMzI1MDBa +MB8GCSqGSIb3DQEJBDESBBCWaa5hG1eeg+oQK2tJ3cD5MGwGCSqGSIb3DQEJNDFfMF0wTw +YLKoZIhvcNAQkQAw0EQAECAwQFBgcICQoLDA0ODxAREhMEFRYXGBkaGxwdHh8gISIjBCUm +JygpKissLS4vMDEyMwQ1Njc4OTo7PD0+P0CiCgYIKwYBBQUIAQIEFLjUxQ9PJFzFnWraxb +EIbVbg2xql +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_ct_authData, asn1Object['contentType']) + + ad, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.AuthenticatedData()) + + self.assertFalse(rest) + self.assertTrue(ad.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(ad)) + self.assertEqual(0, ad['version']) + self.assertEqual( + rfc6210.id_alg_MD5_XOR_EXPERIMENT, ad['digestAlgorithm']['algorithm']) + + mac_alg_p, rest = der_decoder( + ad['digestAlgorithm']['parameters'], + asn1Spec=rfc5280.algorithmIdentifierMap[ad['digestAlgorithm']['algorithm']]) + + self.assertFalse(rest) + self.assertTrue(mac_alg_p.prettyPrint()) + self.assertEqual( + ad['digestAlgorithm']['parameters'], der_encoder(mac_alg_p)) + self.assertEqual("0x01020304", mac_alg_p.prettyPrint()[:10]) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc6211.py b/tests/test_rfc6211.py new file mode 100644 index 0000000..040b17a --- /dev/null +++ b/tests/test_rfc6211.py @@ -0,0 +1,122 @@ +# +# 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 +import unittest + +from pyasn1.type import univ + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc6211 + + +class SignedMessageTestCase(unittest.TestCase): + signed_message_pem_text = """\ +MIIEyAYJKoZIhvcNAQcCoIIEuTCCBLUCAQExDTALBglghkgBZQMEAgIwUQYJKoZI +hvcNAQcBoEQEQkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbg0KDQpXYXRzb24sIGNv +bWUgaGVyZSAtIEkgd2FudCB0byBzZWUgeW91LqCCAnwwggJ4MIIB/qADAgECAgkA +pbNUKBuwbjswCgYIKoZIzj0EAwMwPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZB +MRAwDgYDVQQHDAdIZXJuZG9uMREwDwYDVQQKDAhCb2d1cyBDQTAeFw0xOTA1Mjkx +NDQ1NDFaFw0yMDA1MjgxNDQ1NDFaMHAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJW +QTEQMA4GA1UEBxMHSGVybmRvbjEQMA4GA1UEChMHRXhhbXBsZTEOMAwGA1UEAxMF +QWxpY2UxIDAeBgkqhkiG9w0BCQEWEWFsaWNlQGV4YW1wbGUuY29tMHYwEAYHKoZI +zj0CAQYFK4EEACIDYgAE+M2fBy/sRA6V1pKFqecRTE8+LuAHtZxes1wmJZrBBg+b +z7uYZfYQxI3dVB0YCSD6Mt3yXFlnmfBRwoqyArbjIBYrDbHBv2k8Csg2DhQ7qs/w +to8hMKoFgkcscqIbiV7Zo4GUMIGRMAsGA1UdDwQEAwIHgDBCBglghkgBhvhCAQ0E +NRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUgdHJ1c3RlZCBmb3IgYW55IHB1 +cnBvc2UuMB0GA1UdDgQWBBTEuloOPnrjPIGw9AKqaLsW4JYONTAfBgNVHSMEGDAW +gBTyNds0BNqlVfK9aQOZsGLs4hUIwTAKBggqhkjOPQQDAwNoADBlAjBjuR/RNbgL +3kRhmn+PJTeKaL9sh/oQgHOYTgLmSnv3+NDCkhfKuMNoo/tHrkmihYgCMQC94Mae +rDIrQpi0IDh+v0QSAv9rMife8tClafXWtDwwL8MS7oAh0ymT446Uizxx3PUxggHM +MIIByAIBATBMMD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwH +SGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0ECCQCls1QoG7BuOzALBglghkgBZQME +AgKggfIwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwNTI5MTgyMzE5WjAoBgkqhkiG9w0BCTQxGzAZMAsGCWCGSAFlAwQCAqEKBggq +hkjOPQQDAzA/BgkqhkiG9w0BCQQxMgQwtuQipP2CZx7U96rGbUT06LC5jVFYccZW +5/CaNvpcrOPiChDm2vI3m4k300z5mSZsME0GCyqGSIb3DQEJEAIBMT4wPAQgx08h +D2QnVwj1DoeRELNtdZ0PffW4BQIvcwwVc/goU6OAAQEwFTATgRFhbGljZUBleGFt +cGxlLmNvbTAKBggqhkjOPQQDAwRnMGUCMQChIMyN1nTN+LLQcYJuhWT297vSKMDK +fIUedSwWYrcSnSa1pq2s3Wue+pNBfecEjYECMGrUNu1UpWdafEJulP9Vz76qOPMa +5V/AnTEV5zkmzRle8sffN+nQ+SGkoos5zpI1kA== +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.signed_message_pem_text) + asn1Object, rest = der_decoder (substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + sd, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.SignedData()) + + self.assertFalse(rest) + self.assertTrue(sd.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(sd)) + + for sa in sd['signerInfos'][0]['signedAttrs']: + sat = sa['attrType'] + sav0 = sa['attrValues'][0] + + if sat in rfc6211.id_aa_cmsAlgorithmProtect: + sav, rest = der_decoder( + sav0, asn1Spec=rfc6211.CMSAlgorithmProtection()) + + self.assertFalse(rest) + self.assertTrue(sav.prettyPrint()) + self.assertEqual(sav0, der_encoder(sav)) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.signed_message_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertIn(asn1Object['contentType'], rfc5652.cmsContentTypesMap) + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + sd = asn1Object['content'] + + self.assertEqual( + rfc5652.CMSVersion().subtype(value='v1'), sd['version']) + + ect = sd['encapContentInfo']['eContentType'] + + self.assertIn(ect, rfc5652.cmsContentTypesMap) + self.assertEqual(rfc5652.id_data, ect) + + for sa in sd['signerInfos'][0]['signedAttrs']: + if sa['attrType'] == rfc6211.id_aa_cmsAlgorithmProtect: + self.assertIn(sa['attrType'], rfc5652.cmsAttributesMap) + + sav0 = sa['attrValues'][0] + digest_oid = univ.ObjectIdentifier('2.16.840.1.101.3.4.2.2') + sig_oid = univ.ObjectIdentifier('1.2.840.10045.4.3.3') + + self.assertEqual( + digest_oid, sav0['digestAlgorithm']['algorithm']) + self.assertEqual( + sig_oid, sav0['signatureAlgorithm']['algorithm']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc6402.py b/tests/test_rfc6402.py new file mode 100755 index 0000000..e970dfa --- /dev/null +++ b/tests/test_rfc6402.py @@ -0,0 +1,157 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import char +from pyasn1.type import namedtype +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc6402 + + +class BackwardCompatibilityTestCase(unittest.TestCase): + pem_text = """\ +MIIEJQYJKoZIhvcNAQcCoIIEFjCCBBICAQMxCzAJBgUrDgMCGgUAMIIDAgYIKwYBBQUHDAKgggL0 +BIIC8DCCAuwweDB2AgECBgorBgEEAYI3CgoBMWUwYwIBADADAgEBMVkwVwYJKwYBBAGCNxUUMUow +SAIBBQwZcGl0dWNoYTEuZW1lYS5ocHFjb3JwLm5ldAwMRU1FQVxwaXR1Y2hhDBpDTUNSZXFHZW5l +cmF0b3IudnNob3N0LmV4ZTCCAmqgggJmAgEBMIICXzCCAcgCAQAwADCBnzANBgkqhkiG9w0BAQEF +AAOBjQAwgYkCgYEA0jm7SSSm2wyEAzuNKtFZFJKo91SrJq9wQwEhEKHDavZwMQOm1rZ2PF8NWCEb +PqrhToQ7rtiGLSZa4dF4bzgmBqQ9aoSfEX4jISt31Vy+skHidXjHHpbsjT24NPhrZgANivL7CxD6 +Ft+s7qS1gL4HRm2twQkqSwOLrE/q2QeXl2UCAwEAAaCCAR0wGgYKKwYBBAGCNw0CAzEMFgo2LjIu +OTIwMC4yMD4GCSqGSIb3DQEJDjExMC8wHQYDVR0OBBYEFMW2skn88gxhONWZQA4sWGBDb68yMA4G +A1UdDwEB/wQEAwIHgDBXBgkrBgEEAYI3FRQxSjBIAgEFDBlwaXR1Y2hhMS5lbWVhLmhwcWNvcnAu +bmV0DAxFTUVBXHBpdHVjaGEMGkNNQ1JlcUdlbmVyYXRvci52c2hvc3QuZXhlMGYGCisGAQQBgjcN +AgIxWDBWAgECHk4ATQBpAGMAcgBvAHMAbwBmAHQAIABTAHQAcgBvAG4AZwAgAEMAcgB5AHAAdABv +AGcAcgBhAHAAaABpAGMAIABQAHIAbwB2AGkAZABlAHIDAQAwDQYJKoZIhvcNAQEFBQADgYEAJZlu +mxjtCxSOQi27jsVdd3y8NSIlzNv0b3LqmzvAly6L+CstXcnuG2MPQqPH9R7tbJonGUniBQO9sQ7C +KhYWj2gfhiEkSID82lV5chINVUFKoUlSiEhWr0tPGgvOaqdsKQcrHfzrsBbFkhDqrFSVy7Yivbnh +qYszKrOjJKiiCPMwADAAMYH5MIH2AgEDgBTFtrJJ/PIMYTjVmUAOLFhgQ2+vMjAJBgUrDgMCGgUA +oD4wFwYJKoZIhvcNAQkDMQoGCCsGAQUFBwwCMCMGCSqGSIb3DQEJBDEWBBTFTkK/OifaFjwqHiJu +xM7qXcg/VzANBgkqhkiG9w0BAQEFAASBgKfC6jOi1Wgy4xxDCQVK9+e5tktL8wE/j2cb9JSqq+aU +5UxEgXEw7q7BoYZCAzcxMRriGzakXr8aXHcgkRJ7XcFvLPUjpmGg9SOZ2sGW4zQdWAwImN/i8loc +xicQmJP+VoMHo/ZpjFY9fYCjNZUArgKsEwK/s+p9yrVVeB1Nf8Mn +""" + + def testDerCodec(self): + layers = { } + layers.update(rfc5652.cmsContentTypesMap) + + getNextLayer = { + rfc5652.id_ct_contentInfo: lambda x: x['contentType'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContentType'], + rfc6402.id_cct_PKIData: lambda x: None + } + + getNextSubstrate = { + rfc5652.id_ct_contentInfo: lambda x: x['content'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContent'], + rfc6402.id_cct_PKIData: lambda x: None + } + + substrate = pem.readBase64fromText(self.pem_text) + + next_layer = rfc5652.id_ct_contentInfo + while next_layer: + asn1Object, rest = der_decoder(substrate, asn1Spec=layers[next_layer]) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + substrate = getNextSubstrate[next_layer](asn1Object) + next_layer = getNextLayer[next_layer](asn1Object) + + + def testOpenTypes(self): + class ClientInformation(univ.Sequence): + pass + + ClientInformation.componentType = namedtype.NamedTypes( + namedtype.NamedType('clientId', univ.Integer()), + namedtype.NamedType('MachineName', char.UTF8String()), + namedtype.NamedType('UserName', char.UTF8String()), + namedtype.NamedType('ProcessName', char.UTF8String()) + ) + + class EnrollmentCSP(univ.Sequence): + pass + + EnrollmentCSP.componentType = namedtype.NamedTypes( + namedtype.NamedType('KeySpec', univ.Integer()), + namedtype.NamedType('Name', char.BMPString()), + namedtype.NamedType('Signature', univ.BitString()) + ) + + openTypeMap = { + # attributes + univ.ObjectIdentifier('1.3.6.1.4.1.311.13.2.3'): char.IA5String(), + univ.ObjectIdentifier('1.3.6.1.4.1.311.13.2.2'): EnrollmentCSP(), + univ.ObjectIdentifier('1.3.6.1.4.1.311.21.20'): ClientInformation(), + # algorithm identifier parameters + univ.ObjectIdentifier('1.2.840.113549.1.1.1'): univ.Null(""), + univ.ObjectIdentifier('1.2.840.113549.1.1.5'): univ.Null(""), + univ.ObjectIdentifier('1.2.840.113549.1.1.11'): univ.Null(""), + } + + openTypeMap.update(rfc5652.cmsAttributesMap) + openTypeMap.update(rfc6402.cmcControlAttributesMap) + + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=rfc5652.ContentInfo(), decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + eci = asn1Object['content']['encapContentInfo'] + + self.assertEqual(rfc6402.id_cct_PKIData, eci['eContentType']) + + substrate = eci['eContent'] + asn1Object, rest = der_decoder( + substrate, asn1Spec=rfc6402.PKIData(), openTypes=openTypeMap, + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + for req in asn1Object['reqSequence']: + cr = req['tcr']['certificationRequest'] + + sig_alg = cr['signatureAlgorithm'] + + self.assertIn(sig_alg['algorithm'], openTypeMap) + self.assertEqual(univ.Null(""), sig_alg['parameters']) + + cri = cr['certificationRequestInfo'] + spki_alg = cri['subjectPublicKeyInfo']['algorithm'] + + self.assertIn(spki_alg['algorithm'], openTypeMap) + self.assertEqual(univ.Null(""), spki_alg['parameters']) + + attrs = cr['certificationRequestInfo']['attributes'] + for attr in attrs: + self.assertIn( attr['attrType'], openTypeMap) + + if attr['attrType'] == univ.ObjectIdentifier('1.3.6.1.4.1.311.13.2.3'): + self.assertEqual("6.2.9200.2", attr['attrValues'][0]) + + else: + self.assertTrue(attr['attrValues'][0].hasValue()) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc6482.py b/tests/test_rfc6482.py new file mode 100644 index 0000000..c2f6a94 --- /dev/null +++ b/tests/test_rfc6482.py @@ -0,0 +1,116 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc6482 + + +class RPKIROATestCase(unittest.TestCase): + roa_pem_text = """\ +MIIGvwYJKoZIhvcNAQcCoIIGsDCCBqwCAQMxDTALBglghkgBZQMEAgEwKgYLKoZIhvcNAQkQ +ARigGwQZMBcCAwDj+zAQMA4EAgABMAgwBgMEAJMcLaCCBLwwggS4MIIDoKADAgECAgIGGDAN +BgkqhkiG9w0BAQsFADAzMTEwLwYDVQQDEyg2ZDZmYmZhOTc1M2RiOGQ4NDY0MzNkYjUzNTFk +OWE5ZWMwN2M5NmJkMB4XDTE5MDgyMDAwNDkyOVoXDTIwMDcwMTAwMDAwMFowMzExMC8GA1UE +AxMoNUI4M0REODdERTlBQzdDNkUzNEI4NzdERjUwMUEyQjEyMzBBODFCNDCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJcnDgSUtiQeelGQsTx2Ou5cgmfq6KPSEgMz/XyZrRzj +wcqUQ/DyMYHyRJK8umKZjfMu+rItoPSkE26Wi9PcSnfuY+SyS9chTAtNOGMES6MbtHjNTmBF +Xar5CFGM8teLIRHlCcScesgSR7q2eKgQ+cLiLTZnol0Mpmuf2NIs+V63Y4Hn/T7QOoudg9nU +tmsh31hUN4jIENEXFvNDovkray25rl9aqFfW+dtkoNtdJjp367nNXCdp3GdE/3z0SIqT8wnh +F67tgR22mwzex3umteQBwmM+iR28vuHL4E5jwRKBoiEgGPYqq7gbfkcoFtR3AV6QGKSK2aJU +mUi+9VheS78CAwEAAaOCAdQwggHQMB0GA1UdDgQWBBRbg92H3prHxuNLh331AaKxIwqBtDAf +BgNVHSMEGDAWgBRtb7+pdT242EZDPbU1HZqewHyWvTAYBgNVHSABAf8EDjAMMAoGCCsGAQUF +Bw4CMFAGA1UdHwRJMEcwRaBDoEGGP3JzeW5jOi8vY2EucmcubmV0L3Jwa2kvUkduZXQtT1Uv +YlctX3FYVTl1TmhHUXoyMU5SMmFuc0I4bHIwLmNybDBkBggrBgEFBQcBAQRYMFYwVAYIKwYB +BQUHMAKGSHJzeW5jOi8vcnBraS5yaXBlLm5ldC9yZXBvc2l0b3J5L0RFRkFVTFQvYlctX3FY +VTl1TmhHUXoyMU5SMmFuc0I4bHIwLmNlcjAOBgNVHQ8BAf8EBAMCB4AwgYoGCCsGAQUFBwEL +BH4wfDBLBggrBgEFBQcwC4Y/cnN5bmM6Ly9jYS5yZy5uZXQvcnBraS9SR25ldC1PVS9XNFBk +aDk2YXg4YmpTNGQ5OVFHaXNTTUtnYlEucm9hMC0GCCsGAQUFBzANhiFodHRwczovL2NhLnJn +Lm5ldC9ycmRwL25vdGlmeS54bWwwHwYIKwYBBQUHAQcBAf8EEDAOMAwEAgABMAYDBACTHC0w +DQYJKoZIhvcNAQELBQADggEBAKhhoJ3XtHejvG6XkFaCTxJci10gOgNvvPFWqz+CfOX2LmB0 +N3QhYjLiAZbfYSOxNReyL4bWDK/tpZgVA2VHuS8GB8fI8+nauQUiP38orVXKAbcUUxo7UkEM +HxQ5T61FtXrEZx8hgKTlsfof0G2Q+baSJzNV2MIUgHmSszL4Mx/fHUXv8b7l/5mZQbdv3cZ9 +SbODHD0iOVAzK3fmHeuA4roSOk4mBQDWNRY1Ok+xH/HMDQdoOVtbfy57TZI2W7O2uxfElKvx +fBeEc9TOaWqDz0xvmJ6bdZnmWRuvqW1475mhxi0s/I4eE2ZdaCinvrgrglBp/jpZi1jitY14 +dx+A1PMxggGqMIIBpgIBA4AUW4Pdh96ax8bjS4d99QGisSMKgbQwCwYJYIZIAWUDBAIBoGsw +GgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEYMBwGCSqGSIb3DQEJBTEPFw0xOTA4MjAwMDQ5 +MjlaMC8GCSqGSIb3DQEJBDEiBCCfuHnOmhF2iBF3JXMOnoZCJzmE+Tcf8b+zObvDUpUddzAN +BgkqhkiG9w0BAQEFAASCAQBDlJIMKCqWsFV/tQj/XvpSJUxJybG+zwjrUKm4yTKv8QEGOzOD +aIL6irSOhhXeax6Lw0P2J7x+L3jGW1we1qWslumEDTr9kTE+kN/6rZuptUhwdrXcu3p9G6gJ +mAUQtzqe2jRN1T3eSBfz1CNU3C7+jSHXOc+4Tea5mKiVddsjotYHXX0PbSCS/ZZ1yzdeES0o +KWhXhW9ogS0bwtXWVTrciSekaRpp2n/pqcVEDxWg/5NpPiDlPNrRL/9eTEHFp940RAUfhbBh +pbC2J02N0KgxUJxIJnGnpZ7rXKpG4jMiTVry7XB9bnFxCvZGBdjQW1Hagrfpl2TiVxQFvJWl +IzU1 +""" + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.roa_pem_text) + + layers = {} + layers.update(rfc5652.cmsContentTypesMap) + + getNextLayer = { + rfc5652.id_ct_contentInfo: lambda x: x['contentType'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContentType'], + rfc6482.id_ct_routeOriginAuthz: lambda x: None + } + + getNextSubstrate = { + rfc5652.id_ct_contentInfo: lambda x: x['content'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContent'], + rfc6482.id_ct_routeOriginAuthz: lambda x: None + } + + next_layer = rfc5652.id_ct_contentInfo + while next_layer: + asn1Object, rest = der_decoder(substrate, asn1Spec=layers[next_layer]) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + substrate = getNextSubstrate[next_layer](asn1Object) + next_layer = getNextLayer[next_layer](asn1Object) + + self.assertEqual(0, asn1Object['version']) + self.assertEqual(58363, asn1Object['asID']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.roa_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=rfc5652.ContentInfo(), decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + oid = asn1Object['content']['encapContentInfo']['eContentType'] + substrate = asn1Object['content']['encapContentInfo']['eContent'] + + self.assertIn(oid, rfc5652.cmsContentTypesMap) + + asn1Object, rest = der_decoder( + substrate, asn1Spec=rfc5652.cmsContentTypesMap[oid], + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(0, asn1Object['version']) + self.assertEqual(58363, asn1Object['asID']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc6486.py b/tests/test_rfc6486.py new file mode 100644 index 0000000..1e0075c --- /dev/null +++ b/tests/test_rfc6486.py @@ -0,0 +1,122 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc6486 + + +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 = rfc5652.cmsContentTypesMap.copy() + + 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_decoder(substrate, asn1Spec=layers[next_layer]) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + substrate = getNextSubstrate[next_layer](asn1Object) + next_layer = getNextLayer[next_layer](asn1Object) + + self.assertEqual(0, asn1Object['version']) + + for f in asn1Object['fileList']: + self.assertEqual('ZXSGBDBkL82TFGHuE4VOYtJP-E4.crl', f['file']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.manifest_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=rfc5652.ContentInfo(), decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + oid = asn1Object['content']['encapContentInfo']['eContentType'] + substrate = asn1Object['content']['encapContentInfo']['eContent'] + + self.assertIn(oid, rfc5652.cmsContentTypesMap) + + asn1Object, rest = der_decoder( + substrate, asn1Spec=rfc5652.cmsContentTypesMap[oid], + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(0, asn1Object['version']) + + for f in asn1Object['fileList']: + self.assertEqual('ZXSGBDBkL82TFGHuE4VOYtJP-E4.crl', f['file']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc6487.py b/tests/test_rfc6487.py new file mode 100644 index 0000000..9e42d07 --- /dev/null +++ b/tests/test_rfc6487.py @@ -0,0 +1,146 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc6487 + + +class CertificateWithManifestTestCase(unittest.TestCase): + rpki_cert_pem_text = """\ +MIIGCTCCBPGgAwIBAgICKJgwDQYJKoZIhvcNAQELBQAwRjERMA8GA1UEAxMIQTkwREM1QkUx +MTAvBgNVBAUTKDBDRkNFNzc4NTdGQ0YwMUYzOUQ5OUE2MkI0QUE2MkU2MTU5RTc2RjgwHhcN +MTkwODA2MDQwMzIyWhcNMjAxMDMxMDAwMDAwWjBGMREwDwYDVQQDEwhBOTFEMTY5MTExMC8G +A1UEBRMoREMwNEFGMTk4Qzk3RjI1ODJGMTVBRERFRUU3QzY4MjYxMUNBREE1MTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMksR6bPbZFpxlXID/2dhYFuS11agb6ACDUFJpII +41uw65tFIPT+Y4laccnYRcWPWMTvHLyj0ggU+bc2zJCTYfmGD/GW/Q3WW0A3niBCdXDfkrp2 +DXvSTASJ5+wtVb+AE74C4Mr3UiMOXhJre1rRd5Lq7o6+TEKbVkmUrmTlbsz2Vs2F4//t5sCr +WjAVP9D5jUBGH2MInbleBP1Bwf+kIxD16OKftRb/vGLzk1UhLsbq22GGE0vZ2hnJP3CbyXkN +dLBraErzvyCnqYF7/yA0JL0KWRDwr7a9y37s8O3xOxhA/dL8hLZXllzJmoxvxHmq8D+5CjHv +2/EmH8ODGm2aAzcCAwEAAaOCAv8wggL7MB0GA1UdDgQWBBTcBK8ZjJfyWC8Vrd7ufGgmEcra +UTAfBgNVHSMEGDAWgBQM/Od4V/zwHznZmmK0qmLmFZ52+DAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zBzBgNVHR8EbDBqMGigZqBkhmJyc3luYzovL3Jwa2kuYXBuaWMubmV0 +L3JlcG9zaXRvcnkvQjMyMkE1RjQxRDY2MTFFMkEzRjI3RjdDNzJGRDFGRjIvRFB6bmVGZjg4 +Qjg1MlpwaXRLcGk1aFdlZHZnLmNybDB+BggrBgEFBQcBAQRyMHAwbgYIKwYBBQUHMAKGYnJz +eW5jOi8vcnBraS5hcG5pYy5uZXQvcmVwb3NpdG9yeS85ODA2NTJFMEI3N0UxMUU3QTk2QTM5 +NTIxQTRGNEZCNC9EUHpuZUZmODhCODUyWnBpdEtwaTVoV2VkdmcuY2VyMEoGA1UdIAEB/wRA +MD4wPAYIKwYBBQUHDgIwMDAuBggrBgEFBQcCARYiaHR0cHM6Ly93d3cuYXBuaWMubmV0L1JQ +S0kvQ1BTLnBkZjCCASgGCCsGAQUFBwELBIIBGjCCARYwXwYIKwYBBQUHMAWGU3JzeW5jOi8v +cnBraS5hcG5pYy5uZXQvbWVtYmVyX3JlcG9zaXRvcnkvQTkxRDE2OTEvNTBDNjkyOTI5RDI0 +MTFFNzg2MUEyMjZCQzRGOUFFMDIvMH4GCCsGAQUFBzAKhnJyc3luYzovL3Jwa2kuYXBuaWMu +bmV0L21lbWJlcl9yZXBvc2l0b3J5L0E5MUQxNjkxLzUwQzY5MjkyOUQyNDExRTc4NjFBMjI2 +QkM0RjlBRTAyLzNBU3ZHWXlYOGxndkZhM2U3bnhvSmhISzJsRS5tZnQwMwYIKwYBBQUHMA2G +J2h0dHBzOi8vcnJkcC5hcG5pYy5uZXQvbm90aWZpY2F0aW9uLnhtbDArBggrBgEFBQcBBwEB +/wQcMBowGAQCAAEwEgMEAdQI5gMEAdQI/gMEAdRcZjANBgkqhkiG9w0BAQsFAAOCAQEAGvJ+ +s7VgIZk8LDSz6uvsyX80KzZgaqMF7sMsqln0eo5KiGGBHjwvZuiDf46xbNseWW2nwAHmjLda +osCbcTGVu0JzFYBdkimgyHiq2l8yEchh5BUXr8x4CQIxwGEZEOlEp5mRa/AfHVEfDeMm7mob +eiCfyTC8q8KH9Tb/rY192kBe+n9MuRyn7TkimV5eYMdwWMyT/VSBCQzzfJ0r+S9o0rBYWH9k +HDFd3u1ztO8WGjH/LOehoO30xsm52kbxZjc4SJWubgBgxTMIWyjPHbKqCF44NwYev/6eFcOC ++KTEQ/hydcURm3YtX7EZLDtksWB2me576J8opeLsbNeNgzfJpg== +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + access_methods = [ + rfc6487.id_ad_rpkiManifest, + rfc6487.id_ad_signedObject, + ] + + substrate = pem.readBase64fromText(self.rpki_cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + count = 0 + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_pe_subjectInfoAccess: + extnValue, rest = der_decoder( + extn['extnValue'], asn1Spec=rfc5280.SubjectInfoAccessSyntax()) + for ad in extnValue: + if ad['accessMethod'] in access_methods: + uri = ad['accessLocation']['uniformResourceIdentifier'] + self.assertIn('rpki.apnic.net', uri) + count += 1 + + self.assertEqual(1, count) + + +class CertificateWithSignedObjectTestCase(unittest.TestCase): + rpki_cert_pem_text = """\ +MIIEuDCCA6CgAwIBAgICBhgwDQYJKoZIhvcNAQELBQAwMzExMC8GA1UEAxMoNmQ2 +ZmJmYTk3NTNkYjhkODQ2NDMzZGI1MzUxZDlhOWVjMDdjOTZiZDAeFw0xOTA4MjAw +MDQ5MjlaFw0yMDA3MDEwMDAwMDBaMDMxMTAvBgNVBAMTKDVCODNERDg3REU5QUM3 +QzZFMzRCODc3REY1MDFBMkIxMjMwQTgxQjQwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQCXJw4ElLYkHnpRkLE8djruXIJn6uij0hIDM/18ma0c48HKlEPw +8jGB8kSSvLpimY3zLvqyLaD0pBNulovT3Ep37mPkskvXIUwLTThjBEujG7R4zU5g +RV2q+QhRjPLXiyER5QnEnHrIEke6tnioEPnC4i02Z6JdDKZrn9jSLPlet2OB5/0+ +0DqLnYPZ1LZrId9YVDeIyBDRFxbzQ6L5K2stua5fWqhX1vnbZKDbXSY6d+u5zVwn +adxnRP989EiKk/MJ4Reu7YEdtpsM3sd7prXkAcJjPokdvL7hy+BOY8ESgaIhIBj2 +Kqu4G35HKBbUdwFekBikitmiVJlIvvVYXku/AgMBAAGjggHUMIIB0DAdBgNVHQ4E +FgQUW4Pdh96ax8bjS4d99QGisSMKgbQwHwYDVR0jBBgwFoAUbW+/qXU9uNhGQz21 +NR2ansB8lr0wGAYDVR0gAQH/BA4wDDAKBggrBgEFBQcOAjBQBgNVHR8ESTBHMEWg +Q6BBhj9yc3luYzovL2NhLnJnLm5ldC9ycGtpL1JHbmV0LU9VL2JXLV9xWFU5dU5o +R1F6MjFOUjJhbnNCOGxyMC5jcmwwZAYIKwYBBQUHAQEEWDBWMFQGCCsGAQUFBzAC +hkhyc3luYzovL3Jwa2kucmlwZS5uZXQvcmVwb3NpdG9yeS9ERUZBVUxUL2JXLV9x +WFU5dU5oR1F6MjFOUjJhbnNCOGxyMC5jZXIwDgYDVR0PAQH/BAQDAgeAMIGKBggr +BgEFBQcBCwR+MHwwSwYIKwYBBQUHMAuGP3JzeW5jOi8vY2EucmcubmV0L3Jwa2kv +UkduZXQtT1UvVzRQZGg5NmF4OGJqUzRkOTlRR2lzU01LZ2JRLnJvYTAtBggrBgEF +BQcwDYYhaHR0cHM6Ly9jYS5yZy5uZXQvcnJkcC9ub3RpZnkueG1sMB8GCCsGAQUF +BwEHAQH/BBAwDjAMBAIAATAGAwQAkxwtMA0GCSqGSIb3DQEBCwUAA4IBAQCoYaCd +17R3o7xul5BWgk8SXItdIDoDb7zxVqs/gnzl9i5gdDd0IWIy4gGW32EjsTUXsi+G +1gyv7aWYFQNlR7kvBgfHyPPp2rkFIj9/KK1VygG3FFMaO1JBDB8UOU+tRbV6xGcf +IYCk5bH6H9BtkPm2kiczVdjCFIB5krMy+DMf3x1F7/G+5f+ZmUG3b93GfUmzgxw9 +IjlQMyt35h3rgOK6EjpOJgUA1jUWNTpPsR/xzA0HaDlbW38ue02SNluztrsXxJSr +8XwXhHPUzmlqg89Mb5iem3WZ5lkbr6lteO+ZocYtLPyOHhNmXWgop764K4JQaf46 +WYtY4rWNeHcfgNTz +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + access_methods = [ + rfc6487.id_ad_rpkiManifest, + rfc6487.id_ad_signedObject, + ] + + substrate = pem.readBase64fromText(self.rpki_cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + count = 0 + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_pe_subjectInfoAccess: + extnValue, rest = der_decoder( + extn['extnValue'], asn1Spec=rfc5280.SubjectInfoAccessSyntax()) + for ad in extnValue: + if ad['accessMethod'] in access_methods: + uri = ad['accessLocation']['uniformResourceIdentifier'] + self.assertIn('ca.rg.net', uri) + count += 1 + + self.assertEqual(1, count) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc6664.py b/tests/test_rfc6664.py new file mode 100644 index 0000000..83278a7 --- /dev/null +++ b/tests/test_rfc6664.py @@ -0,0 +1,103 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5480 +from pyasn1_modules import rfc5751 +from pyasn1_modules import rfc6664 + + +class SMIMECapabilitiesTestCase(unittest.TestCase): + smime_capabilities_pem_text = """\ +MIICOjAJBgUrDgMCGgUAMA0GCWCGSAFlAwQCBAUAMA0GCWCGSAFlAwQCAQUAMA0G +CWCGSAFlAwQCAgUAMA0GCWCGSAFlAwQCAwUAMBUGCSqGSIb3DQEBATAIAgIEAAIC +EAAwFQYJKoZIhvcNAQEHMAgCAgQAAgIQADAVBgkqhkiG9w0BAQowCAICBAACAhAA +MBUGByqGSM44BAGgCjAIAgIEAAICDAAwggEvBgcqhkjOPgIBoYIBIjCCAR4CgYEA +i6Ued8R33vkopJwCvy/ZZv2TtddPXPYmJK4jyFv+TDJTPqnP7XUZCqRuhCyKX10z +7SgiZs6qlSMk5gCa8shPF8NCHtps2D1OVC7yppZUJI07FoDxoEAZHImdAFvYIA/V +cGYpYOKod4kju0/e4VUBZ6Qoer5vKTh+lD/+ZKa/WSUCFQDc3W87QSZSX6ggdbeI +fzb0rsAhbwKBgCEz/o4WJPUZ4HffJfuXHIGrkPnCxFAYDRtlqueswV0Gy6LunipE +Iu3nCzYkZhMatyFNyzo+NusEsS+9isOhT8jhL93nSBZCSRBy+GfmSXlXv/3c8mtH +XTie5JOqjRdonPr4g/+VZvMkcioooNrhx/zICHrC3WZ72871/n/z9M+dMCMGByqG +SM49AgEwGAYIKoZIzj0DAQcGBSuBBAAiBgUrgQQAIzAhBgUrgQQBDTAYBggqhkjO +PQMBBwYFK4EEACIGBSuBBAAjMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEFAA== +""" + + def setUp(self): + self.asn1Spec = rfc5751.SMIMECapabilities() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.smime_capabilities_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + count = 0 + for cap in asn1Object: + if cap['capabilityID'] in rfc5751.smimeCapabilityMap.keys(): + substrate = cap['parameters'] + cap_p, rest = der_decoder( + substrate, asn1Spec=rfc5751.smimeCapabilityMap[cap['capabilityID']]) + self.assertFalse(rest) + self.assertTrue(cap_p.prettyPrint()) + self.assertEqual(substrate, der_encoder(cap_p)) + count += 1 + + self.assertEqual(8, count) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.smime_capabilities_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + parameterValue = { + rfc6664.rsaEncryption: lambda x: x['maxKeySize'], + rfc6664.id_RSAES_OAEP: lambda x: x['maxKeySize'], + rfc6664.id_RSASSA_PSS: lambda x: x['minKeySize'], + rfc6664.id_dsa: lambda x: x['keySizes']['maxKeySize'], + rfc6664.dhpublicnumber: lambda x: x['keyParams']['q'] % 1023, + rfc6664.id_ecPublicKey: lambda x: x[0]['namedCurve'], + rfc6664.id_ecMQV: lambda x: x[1]['namedCurve'], + } + + expectedValue = { + rfc6664.rsaEncryption: 4096, + rfc6664.id_RSAES_OAEP: 4096, + rfc6664.id_RSASSA_PSS: 1024, + rfc6664.id_dsa: 3072, + rfc6664.dhpublicnumber: 257, + rfc6664.id_ecPublicKey: rfc5480.secp256r1, + rfc6664.id_ecMQV: rfc5480.secp384r1, + } + + count = 0 + for cap in asn1Object: + if cap['capabilityID'] in parameterValue.keys(): + pValue = parameterValue[cap['capabilityID']](cap['parameters']) + eValue = expectedValue[cap['capabilityID']] + self.assertEqual(eValue, pValue) + count += 1 + + self.assertEqual(7, count) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc6955.py b/tests/test_rfc6955.py new file mode 100644 index 0000000..443d70d --- /dev/null +++ b/tests/test_rfc6955.py @@ -0,0 +1,101 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5480 +from pyasn1_modules import rfc6402 +from pyasn1_modules import rfc6955 + + +class CertificationRequestTestCase(unittest.TestCase): + pem_text = """\ +MIIDPDCCArsCAQAwTjELMAkGA1UEBhMCVVMxETAPBgNVBAoTCFhFVEkgSW5jMRAw +DgYDVQQLEwdUZXN0aW5nMRowGAYDVQQDExFQS0lYIEV4YW1wbGUgVXNlcjCCAkEw +ggG2BgcqhkjOPgIBMIIBqQKBgQCUhOBFbH9pUWI+VoB8aOfFqZ6edHSU7ZCMHcTh +ShSC9dKUDBnjuRC7EbnlpfuOIVFjAoaqBrghNrZ/Nt/R1mhbeXwdWhR1H2qTdZPO +u5dyivAPI51H9tSzx/D05vYrwjLhiWe+fgau+NABa4sq9QLXtqhjlIOwGzF9Uhre +5QOFJwKBgCamMixaK9QzK1zcBodTP5AGYVA4PtK5fYEcEhDFDFPUZNGOMAcIjN0/ +Ci8s1ht/V4bQ2rtuNioY6NO8cDF6SLZOGG7dHyIG6z/q1EFp2ZveR5V6cpHSCX9J +XDsDM1HI8Tma/wTVbn6UPQO49jEVJkiVqFzeR4i0aToAp4ae2tHNAiEA6HL6lvAR +QPXy3P07XXiUsYUB5Wk3IfclubpxSvxgMPsCYQCjkQHAqG6kTaBW/Gz+H6ewzQ+U +hwwlvpd2jevlpAldq4PNgAs1Z38MjqcxmDKFOUCdEZjY3rh/hpuvjWc9tna0YS8h +4UsOaP9TPofd2HFWaEfc9yBjSzxfeHGD5nCe4pIwGgMVABzVOg0Xgm0KgXWBRhCO +PtsJ5Jg0AgE3A4GEAAKBgBNjoYUEjEaoiOv0XqiTdK79rp6WJxJlxEwHBj4Y/pS4 +qHlIvS40tkfKBDCh7DP9GgstnlDJeA+uauy1a2q+slzasp94LLl34nkrJb8uC1lK +k0v4s+yBNK6XR1LgqCmY7NGwyitveovbTo2lFX5+rzNiCZ4PEUSMwY2iEZ5T77Lo +oCEwHwYJKoZIhvcNAQkOMRIwEDAOBgNVHQ8BAf8EBAMCAwgwDAYIKwYBBQUHBgMF +AANtADBqMFIwSDELMAkGA1UEBhMCVVMxETAPBgNVBAoTCFhFVEkgSW5jMRAwDgYD +VQQLEwdUZXN0aW5nMRQwEgYDVQQDEwtSb290IERTQSBDQQIGANo5tuLLBBQtBXf+ +Xo9l9a+tyVybAsCoiClhYw== +""" + + def setUp(self): + self.asn1Spec = rfc6402.CertificationRequest() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + spki_a = asn1Object['certificationRequestInfo']['subjectPublicKeyInfo']['algorithm'] + + self.assertEqual(rfc5480.dhpublicnumber, spki_a['algorithm']) + self.assertIn(spki_a['algorithm'], rfc5280.algorithmIdentifierMap) + + params, rest = der_decoder( + spki_a['parameters'], asn1Spec=rfc6955.DomainParameters()) + + self.assertFalse(rest) + self.assertTrue(params.prettyPrint()) + self.assertEqual(spki_a['parameters'], der_encoder(params)) + self.assertEqual(55, params['validationParms']['pgenCounter']) + + sig_a = asn1Object['signatureAlgorithm'] + + self.assertEqual( + rfc6955.id_dhPop_static_sha1_hmac_sha1, sig_a['algorithm']) + self.assertIn(sig_a['algorithm'], rfc5280.algorithmIdentifierMap) + self.assertEqual(sig_a['parameters'], der_encoder(univ.Null(""))) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + spki_a = asn1Object['certificationRequestInfo']['subjectPublicKeyInfo']['algorithm'] + + self.assertEqual(rfc5480.dhpublicnumber, spki_a['algorithm']) + self.assertEqual( + 55, spki_a['parameters']['validationParms']['pgenCounter']) + + sig_a = asn1Object['signatureAlgorithm'] + + self.assertEqual( + rfc6955.id_dhPop_static_sha1_hmac_sha1, sig_a['algorithm']) + self.assertEqual(univ.Null(""), sig_a['parameters']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc6960.py b/tests/test_rfc6960.py new file mode 100644 index 0000000..151c934 --- /dev/null +++ b/tests/test_rfc6960.py @@ -0,0 +1,176 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc4055 +from pyasn1_modules import rfc6960 + + +class OCSPRequestTestCase(unittest.TestCase): + ocsp_req_pem_text = """\ +MGowaDBBMD8wPTAJBgUrDgMCGgUABBS3ZrMV9C5Dko03aH13cEZeppg3wgQUkqR1LKSevoFE63n8 +isWVpesQdXMCBDXe9M+iIzAhMB8GCSsGAQUFBzABAgQSBBBjdJOiIW9EKJGELNNf/rdA +""" + + def setUp(self): + self.asn1Spec = rfc6960.OCSPRequest() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.ocsp_req_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(0, asn1Object['tbsRequest']['version']) + + count = 0 + for extn in asn1Object['tbsRequest']['requestExtensions']: + self.assertIn(extn['extnID'], rfc5280.certificateExtensionsMap) + + ev, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertFalse(rest) + self.assertTrue(ev.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(ev)) + + count += 1 + + self.assertEqual(1, count) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.ocsp_req_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(0, asn1Object['tbsRequest']['version']) + + for req in asn1Object['tbsRequest']['requestList']: + ha = req['reqCert']['hashAlgorithm'] + self.assertEqual(rfc4055.id_sha1, ha['algorithm']) + self.assertEqual(univ.Null(""), ha['parameters']) + + +class OCSPResponseTestCase(unittest.TestCase): + ocsp_resp_pem_text = """\ +MIIEvQoBAKCCBLYwggSyBgkrBgEFBQcwAQEEggSjMIIEnzCCAQ+hgYAwfjELMAkGA1UEBhMCQVUx +EzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEV +MBMGA1UEAxMMc25tcGxhYnMuY29tMSAwHgYJKoZIhvcNAQkBFhFpbmZvQHNubXBsYWJzLmNvbRgP +MjAxMjA0MTExNDA5MjJaMFQwUjA9MAkGBSsOAwIaBQAEFLdmsxX0LkOSjTdofXdwRl6mmDfCBBSS +pHUspJ6+gUTrefyKxZWl6xB1cwIENd70z4IAGA8yMDEyMDQxMTE0MDkyMlqhIzAhMB8GCSsGAQUF +BzABAgQSBBBjdJOiIW9EKJGELNNf/rdAMA0GCSqGSIb3DQEBBQUAA4GBADk7oRiCy4ew1u0N52QL +RFpW+tdb0NfkV2Xyu+HChKiTThZPr9ZXalIgkJ1w3BAnzhbB0JX/zq7Pf8yEz/OrQ4GGH7HyD3Vg +PkMu+J6I3A2An+bUQo99AmCbZ5/tSHtDYQMQt3iNbv1fk0yvDmh7UdKuXUNSyJdHeg27dMNy4k8A +oIIC9TCCAvEwggLtMIICVqADAgECAgEBMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAkFVMRMw +EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxFTAT +BgNVBAMTDHNubXBsYWJzLmNvbTEgMB4GCSqGSIb3DQEJARYRaW5mb0Bzbm1wbGFicy5jb20wHhcN +MTIwNDExMTMyNTM1WhcNMTMwNDExMTMyNTM1WjB+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29t +ZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRUwEwYDVQQDEwxzbm1w +bGFicy5jb20xIDAeBgkqhkiG9w0BCQEWEWluZm9Ac25tcGxhYnMuY29tMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQDDDU5HOnNV8I2CojxB8ilIWRHYQuaAjnjrETMOprouDHFXnwWqQo/I3m0b +XYmocrh9kDefb+cgc7+eJKvAvBqrqXRnU38DmQU/zhypCftGGfP8xjuBZ1n23lR3hplN1yYA0J2X +SgBaAg6e8OsKf1vcX8Es09rDo8mQpt4G2zR56wIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG ++EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU8Ys2dpJFLMHl +yY57D4BNmlqnEcYwHwYDVR0jBBgwFoAU8Ys2dpJFLMHlyY57D4BNmlqnEcYwDQYJKoZIhvcNAQEF +BQADgYEAWR0uFJVlQId6hVpUbgXFTpywtNitNXFiYYkRRv77McSJqLCa/c1wnuLmqcFcuRUK0oN6 +8ZJDP2HDDKe8MCZ8+sx+CF54eM8VCgN9uQ9XyE7x9XrXDd3Uw9RJVaWSIezkNKNeBE0lDM2jUjC4 +HAESdf7nebz1wtqAOXE1jWF/y8g= +""" + + def setUp(self): + self.asn1Spec = rfc6960.OCSPResponse() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.ocsp_resp_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(0, asn1Object['responseStatus']) + + rb = asn1Object['responseBytes'] + + self.assertIn(rb['responseType'], rfc6960.ocspResponseMap) + + resp, rest = der_decoder( + rb['response'], asn1Spec=rfc6960.ocspResponseMap[rb['responseType']]) + + self.assertFalse(rest) + self.assertTrue(resp.prettyPrint()) + self.assertEqual(rb['response'], der_encoder(resp)) + self.assertEqual(0, resp['tbsResponseData']['version']) + + count = 0 + for extn in resp['tbsResponseData']['responseExtensions']: + self.assertIn(extn['extnID'], rfc5280.certificateExtensionsMap) + + ev, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertFalse(rest) + self.assertTrue(ev.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(ev)) + + count += 1 + + self.assertEqual(1, count) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.ocsp_resp_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(0, asn1Object['responseStatus']) + + rb = asn1Object['responseBytes'] + + self.assertIn(rb['responseType'], rfc6960.ocspResponseMap) + + resp, rest = der_decoder( + rb['response'], + asn1Spec=rfc6960.ocspResponseMap[rb['responseType']], + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(resp.prettyPrint()) + self.assertEqual(rb['response'], der_encoder(resp)) + self.assertEqual(0, resp['tbsResponseData']['version']) + + for rdn in resp['tbsResponseData']['responderID']['byName']['rdnSequence']: + for attr in rdn: + if attr['type'] == rfc5280.id_emailAddress: + self.assertEqual('info@snmplabs.com', attr['value']) + + for r in resp['tbsResponseData']['responses']: + ha = r['certID']['hashAlgorithm'] + self.assertEqual(rfc4055.id_sha1, ha['algorithm']) + self.assertEqual(univ.Null(""), ha['parameters']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc7030.py b/tests/test_rfc7030.py new file mode 100644 index 0000000..7d011f0 --- /dev/null +++ b/tests/test_rfc7030.py @@ -0,0 +1,89 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc7030 + + +class CSRAttrsTestCase(unittest.TestCase): + pem_text = """\ +MEEGCSqGSIb3DQEJBzASBgcqhkjOPQIBMQcGBSuBBAAiMBYGCSqGSIb3DQEJDjEJ +BgcrBgEBAQEWBggqhkjOPQQDAw== +""" + + the_oids = ( + univ.ObjectIdentifier('1.2.840.113549.1.9.7'), + univ.ObjectIdentifier('1.2.840.10045.4.3.3') + ) + + the_attrTypes = ( + univ.ObjectIdentifier('1.2.840.10045.2.1'), + univ.ObjectIdentifier('1.2.840.113549.1.9.14'), + ) + + the_attrVals = ( + '1.3.132.0.34', + '1.3.6.1.1.1.1.22', + ) + + def setUp(self): + self.asn1Spec = rfc7030.CsrAttrs() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + for attr_or_oid in asn1Object: + if attr_or_oid.getName() == 'oid': + self.assertIn(attr_or_oid['oid'], self.the_oids) + + if attr_or_oid.getName() == 'attribute': + self.assertIn( + attr_or_oid['attribute']['attrType'], self.the_attrTypes) + + def testOpenTypes(self): + openTypesMap = rfc5652.cmsAttributesMap.copy() + + for at in self.the_attrTypes: + openTypesMap.update({at: univ.ObjectIdentifier()}) + + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, openTypes=openTypesMap, + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + for attr_or_oid in asn1Object: + if attr_or_oid.getName() == 'attribute': + valString = attr_or_oid['attribute']['attrValues'][0].prettyPrint() + + if attr_or_oid['attribute']['attrType'] == self.the_attrTypes[0]: + self.assertEqual(self.the_attrVals[0], valString) + + if attr_or_oid['attribute']['attrType'] == self.the_attrTypes[1]: + self.assertEqual(self.the_attrVals[1], valString) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc7191.py b/tests/test_rfc7191.py new file mode 100644 index 0000000..40afbd4 --- /dev/null +++ b/tests/test_rfc7191.py @@ -0,0 +1,313 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc7191 + + +class ReceiptRequestTestCase(unittest.TestCase): + message1_pem_text = """\ +MIIGfAYJKoZIhvcNAQcCoIIGbTCCBmkCAQMxDTALBglghkgBZQMEAgIwgb4GCyqGSIb3DQEJ +EAEZoIGuBIGrMIGooEQwIwYLKoZIhvcNAQkQDAExFAwSVmlnaWwgU2VjdXJpdHkgTExDMB0G +CyqGSIb3DQEJEAwDMQ4MDFByZXRlbmQgMDQ4QTBgMF4wVjAbBgsqhkiG9w0BCRAMGzEMDApl +eGFtcGxlSUQxMBUGCyqGSIb3DQEJEAwKMQYMBEhPVFAwIAYLKoZIhvcNAQkQDAsxEQwPa3Rh +LmV4YW1wbGUuY29tBAQxMjM0oIIChzCCAoMwggIKoAMCAQICCQCls1QoG7BuPTAKBggqhkjO +PQQDAzA/MQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkExEDAOBgNVBAcMB0hlcm5kb24xETAP +BgNVBAoMCEJvZ3VzIENBMB4XDTE5MDYxMjE0MzEwNFoXDTIwMDYxMTE0MzEwNFowfDELMAkG +A1UEBhMCVVMxCzAJBgNVBAgTAlZBMRAwDgYDVQQHEwdIZXJuZG9uMRswGQYDVQQKExJWaWdp +bCBTZWN1cml0eSBMTEMxFzAVBgNVBAsTDktleSBNYW5hZ2VtZW50MRgwFgYDVQQDEw9rdGEu +ZXhhbXBsZS5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASX9l7E3VS3GAEiiRrVozgCBQfL +F67IhOxtbQviD/ojhHSQmflLyfRJ8e7+nbWlOLstRc7lgmq+OQVaSlStkzVk/BO1wE5BgUyF +xje+sieUtPRXVqfoVZCJJsgiSbo181ejgZQwgZEwCwYDVR0PBAQDAgeAMEIGCWCGSAGG+EIB +DQQ1FjNUaGlzIGNlcnRpZmljYXRlIGNhbm5vdCBiZSB0cnVzdGVkIGZvciBhbnkgcHVycG9z +ZS4wHQYDVR0OBBYEFG2bXP0Dr7W51YvxZJ8aVuC1rU0PMB8GA1UdIwQYMBaAFPI12zQE2qVV +8r1pA5mwYuziFQjBMAoGCCqGSM49BAMDA2cAMGQCMAZ4lqTtdbaDLFfHywaQYwOWBkL3d0wH +EsNZTW1qQKy/oY3tXc0O6cbJZ5JJb9wk8QIwblXm8+JjdEJHsNjSv4rcJZou4vkMT7PzEme2 +BbMkwOWeIdhmy1vszd8TQgvdb36XMYIDBzCCAwMCAQOAFG2bXP0Dr7W51YvxZJ8aVuC1rU0P +MAsGCWCGSAFlAwQCAqCCAmUwGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEZMBwGCSqGSIb3 +DQEJBTEPFw0xOTA2MTIxOTM1NTFaMCUGCyqGSIb3DQEJEAIHMRYEFCe4nFY7FiJRnReHHHm/ +rIht3/g9MD8GCSqGSIb3DQEJBDEyBDA3gzQlzfvylOn9Rf59kMSa1K2IyOBA5Eoeiyp83Bmj +KasomGorn9htte1iFPbxPRUwggG/BglghkgBZQIBBUExggGwMIIBrAQUJ7icVjsWIlGdF4cc +eb+siG3f+D0wggGSoIH+MH8GCWCGSAFlAgEQAARyMHAxCzAJBgNVBAYTAlVTMQswCQYDVQQI +EwJWQTEQMA4GA1UEBxMHSGVybmRvbjEQMA4GA1UEChMHRXhhbXBsZTEOMAwGA1UEAxMFQWxp +Y2UxIDAeBgkqhkiG9w0BCQEWEWFsaWNlQGV4YW1wbGUuY29tMHsGCWCGSAFlAgEQAARuMGwx +CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJWQTEQMA4GA1UEBxMHSGVybmRvbjEQMA4GA1UEChMH +RXhhbXBsZTEMMAoGA1UEAxMDQm9iMR4wHAYJKoZIhvcNAQkBFg9ib2JAZXhhbXBsZS5jb20w +gY4wgYsGCWCGSAFlAgEQAAR+MHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJWQTEQMA4GA1UE +BxMHSGVybmRvbjEbMBkGA1UEChMSVmlnaWwgU2VjdXJpdHkgTExDMRcwFQYDVQQLEw5LZXkg +TWFuYWdlbWVudDEYMBYGA1UEAxMPa3RhLmV4YW1wbGUuY29tMAoGCCqGSM49BAMDBGYwZAIw +Z7DXliUb8FDKs+BadyCY+IJobPnQ6UoLldMj3pKEowONPifqrbWBJJ5cQQNgW6YuAjBbjSlY +goRV+bq4fdgOOj25JFqa80xnXGtQqjm/7NSII5SbdJk+DT7KCkSbkElkbgQ= +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.message1_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + sd, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.SignedData()) + + for sa in sd['signerInfos'][0]['signedAttrs']: + sat = sa['attrType'] + sav0 = sa['attrValues'][0] + + if sat == rfc7191.id_aa_KP_keyPkgIdAndReceiptReq: + sav, rest = der_decoder( + sav0, asn1Spec=rfc7191.KeyPkgIdentifierAndReceiptReq()) + + self.assertFalse(rest) + self.assertTrue(sav.prettyPrint()) + self.assertEqual(sav0, der_encoder(sav)) + + package_id_pem_text = "J7icVjsWIlGdF4cceb+siG3f+D0=" + package_id = pem.readBase64fromText(package_id_pem_text) + + self.assertEqual(package_id, sav['pkgID']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.message1_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + v3 = rfc5652.CMSVersion().subtype(value='v3') + + self.assertEqual(v3, asn1Object['content']['version']) + + for sa in asn1Object['content']['signerInfos'][0]['signedAttrs']: + if sa['attrType'] == rfc7191.id_aa_KP_keyPkgIdAndReceiptReq: + package_id_pem_text = "J7icVjsWIlGdF4cceb+siG3f+D0=" + package_id = pem.readBase64fromText(package_id_pem_text) + self.assertEqual(package_id, sa['attrValues'][0]['pkgID']) + + +class ReceiptTestCase(unittest.TestCase): + message2_pem_text = """\ +MIIEdAYJKoZIhvcNAQcCoIIEZTCCBGECAQMxDTALBglghkgBZQMEAgIwgawGCmCGSAFlAgEC +TgOggZ0EgZowgZcEFCe4nFY7FiJRnReHHHm/rIht3/g9MH8GCWCGSAFlAgEQAARyMHAxCzAJ +BgNVBAYTAlVTMQswCQYDVQQIEwJWQTEQMA4GA1UEBxMHSGVybmRvbjEQMA4GA1UEChMHRXhh +bXBsZTEOMAwGA1UEAxMFQWxpY2UxIDAeBgkqhkiG9w0BCQEWEWFsaWNlQGV4YW1wbGUuY29t +oIICfDCCAngwggH+oAMCAQICCQCls1QoG7BuOzAKBggqhkjOPQQDAzA/MQswCQYDVQQGEwJV +UzELMAkGA1UECAwCVkExEDAOBgNVBAcMB0hlcm5kb24xETAPBgNVBAoMCEJvZ3VzIENBMB4X +DTE5MDUyOTE0NDU0MVoXDTIwMDUyODE0NDU0MVowcDELMAkGA1UEBhMCVVMxCzAJBgNVBAgT +AlZBMRAwDgYDVQQHEwdIZXJuZG9uMRAwDgYDVQQKEwdFeGFtcGxlMQ4wDAYDVQQDEwVBbGlj +ZTEgMB4GCSqGSIb3DQEJARYRYWxpY2VAZXhhbXBsZS5jb20wdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAT4zZ8HL+xEDpXWkoWp5xFMTz4u4Ae1nF6zXCYlmsEGD5vPu5hl9hDEjd1UHRgJIPoy +3fJcWWeZ8FHCirICtuMgFisNscG/aTwKyDYOFDuqz/C2jyEwqgWCRyxyohuJXtmjgZQwgZEw +CwYDVR0PBAQDAgeAMEIGCWCGSAGG+EIBDQQ1FjNUaGlzIGNlcnRpZmljYXRlIGNhbm5vdCBi +ZSB0cnVzdGVkIGZvciBhbnkgcHVycG9zZS4wHQYDVR0OBBYEFMS6Wg4+euM8gbD0Aqpouxbg +lg41MB8GA1UdIwQYMBaAFPI12zQE2qVV8r1pA5mwYuziFQjBMAoGCCqGSM49BAMDA2gAMGUC +MGO5H9E1uAveRGGaf48lN4pov2yH+hCAc5hOAuZKe/f40MKSF8q4w2ij+0euSaKFiAIxAL3g +xp6sMitCmLQgOH6/RBIC/2syJ97y0KVp9da0PDAvwxLugCHTKZPjjpSLPHHc9TGCARwwggEY +AgEDgBTEuloOPnrjPIGw9AKqaLsW4JYONTALBglghkgBZQMEAgKgejAZBgkqhkiG9w0BCQMx +DAYKYIZIAWUCAQJOAzAcBgkqhkiG9w0BCQUxDxcNMTkwNjEzMTYxNjA4WjA/BgkqhkiG9w0B +CQQxMgQwQSWYpq4jwhMkmS0as0JL3gjYxKLgDfzP2ndTNsAY0m9p8Igp8ZcK4+5n9fXJ43vU +MAoGCCqGSM49BAMDBGgwZgIxAMfq2EJ5pSl9tGOEVJEgZitc266ljrOg5GDjkd2d089qw1A3 +bUcOYuCdivgxVuhlAgIxAPR9JavxziwCbVyBUWOAiKKYfglTgG3AwNmrKDj0NtXUQ9qDmGAc +6L+EAY2P5OVB8Q== +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.message2_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + sd, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.SignedData()) + + self.assertFalse(rest) + self.assertTrue(sd.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(sd)) + + oid = sd['encapContentInfo']['eContentType'] + + self.assertEqual(rfc7191.id_ct_KP_keyPackageReceipt, oid) + + receipt, rest = der_decoder( + sd['encapContentInfo']['eContent'], + asn1Spec=rfc7191.KeyPackageReceipt()) + + self.assertFalse(rest) + self.assertTrue(receipt.prettyPrint()) + self.assertEqual(sd['encapContentInfo']['eContent'], der_encoder(receipt)) + + package_id_pem_text = "J7icVjsWIlGdF4cceb+siG3f+D0=" + package_id = pem.readBase64fromText(package_id_pem_text) + + self.assertEqual(package_id, receipt['receiptOf']['pkgID']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.message2_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + v3 = rfc5652.CMSVersion().subtype(value='v3') + + self.assertEqual(v3, asn1Object['content']['version']) + + for sa in asn1Object['content']['signerInfos'][0]['signedAttrs']: + self.assertIn( sa['attrType'], rfc5652.cmsAttributesMap) + if sa['attrType'] == rfc5652.id_messageDigest: + self.assertIn( + '0x412598a6ae2', sa['attrValues'][0].prettyPrint()) + + ct_oid = asn1Object['content']['encapContentInfo']['eContentType'] + + self.assertIn(ct_oid, rfc5652.cmsContentTypesMap) + self.assertEqual(ct_oid, rfc7191.id_ct_KP_keyPackageReceipt) + + # Since receipt is inside an OCTET STRING, decodeOpenTypes=True cannot + # automatically decode it + sd_eci = asn1Object['content']['encapContentInfo'] + receipt, rest = der_decoder( + sd_eci['eContent'], + asn1Spec=rfc5652.cmsContentTypesMap[sd_eci['eContentType']]) + package_id_pem_text = "J7icVjsWIlGdF4cceb+siG3f+D0=" + package_id = pem.readBase64fromText(package_id_pem_text) + + self.assertEqual(package_id, receipt['receiptOf']['pkgID']) + + +class ErrorTestCase(unittest.TestCase): + message3_pem_text = """\ +MIIEbwYJKoZIhvcNAQcCoIIEYDCCBFwCAQMxDTALBglghkgBZQMEAgIwga0GCmCGSAFlAgEC +TgaggZ4EgZswgZigFgQUJ7icVjsWIlGdF4cceb+siG3f+D0wewYJYIZIAWUCARAABG4wbDEL +MAkGA1UEBhMCVVMxCzAJBgNVBAgTAlZBMRAwDgYDVQQHEwdIZXJuZG9uMRAwDgYDVQQKEwdF +eGFtcGxlMQwwCgYDVQQDEwNCb2IxHjAcBgkqhkiG9w0BCQEWD2JvYkBleGFtcGxlLmNvbQoB +CqCCAncwggJzMIIB+qADAgECAgkApbNUKBuwbjwwCgYIKoZIzj0EAwMwPzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAlZBMRAwDgYDVQQHDAdIZXJuZG9uMREwDwYDVQQKDAhCb2d1cyBDQTAe +Fw0xOTA1MjkxOTIwMTNaFw0yMDA1MjgxOTIwMTNaMGwxCzAJBgNVBAYTAlVTMQswCQYDVQQI +EwJWQTEQMA4GA1UEBxMHSGVybmRvbjEQMA4GA1UEChMHRXhhbXBsZTEMMAoGA1UEAxMDQm9i +MR4wHAYJKoZIhvcNAQkBFg9ib2JAZXhhbXBsZS5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AAQxpGJVLxa83xhyal+rvmMFs4xS6Q19cCDoAvQkkFe0gUC4glxlWWQuf/FvLCRwwscr877D +1FZRBrYKPD6Hxv/UKX6Aimou0TnnxsPk98zZpikn9gTrJn2cF9NCzvPVMfmjgZQwgZEwCwYD +VR0PBAQDAgeAMEIGCWCGSAGG+EIBDQQ1FjNUaGlzIGNlcnRpZmljYXRlIGNhbm5vdCBiZSB0 +cnVzdGVkIGZvciBhbnkgcHVycG9zZS4wHQYDVR0OBBYEFMprZnLeLJtXf5iO4sMq02aOwhql +MB8GA1UdIwQYMBaAFPI12zQE2qVV8r1pA5mwYuziFQjBMAoGCCqGSM49BAMDA2cAMGQCMBVu +hLo58RhCiYsOLZFSR3vWHPDCJBnO1vE1uixqEjONHxlBoeGN2MmWs/9PppcHCwIwN9HB5jPc +J7gTjA9+ipCe+qkztmV+Gy2NBAY6xYC0gh+pb+X5OAI7y7HdctXp+PfrMYIBGzCCARcCAQOA +FMprZnLeLJtXf5iO4sMq02aOwhqlMAsGCWCGSAFlAwQCAqB6MBkGCSqGSIb3DQEJAzEMBgpg +hkgBZQIBAk4GMBwGCSqGSIb3DQEJBTEPFw0xOTA2MTMxNjE2MDhaMD8GCSqGSIb3DQEJBDEy +BDCgXFTUc3ZInjt+MWYkYmXYERk4FgErEZNILlWgVl7Z9pImgLObIpdrGqGPt06/VkwwCgYI +KoZIzj0EAwMEZzBlAjEAsjJ3iWRUteMKBVsjaYeN6TG9NITRTOpRVkSVq55DcnhwS9g9lu8D +iNF8uKtW/lk0AjA7z2q40N0lamXkSU7ECasiWOYV1X4cWGiQwMZDKknBPDqXqB6Es6p4J+qe +0V6+BtY= +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.message3_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + sd, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.SignedData()) + + self.assertFalse(rest) + self.assertTrue(sd.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(sd)) + + oid = sd['encapContentInfo']['eContentType'] + + self.assertEqual(rfc7191.id_ct_KP_keyPackageError, oid) + + kpe, rest = der_decoder( + sd['encapContentInfo']['eContent'], + asn1Spec=rfc7191.KeyPackageError()) + + self.assertFalse(rest) + self.assertTrue(kpe.prettyPrint()) + self.assertEqual(sd['encapContentInfo']['eContent'], der_encoder(kpe)) + + package_id_pem_text = "J7icVjsWIlGdF4cceb+siG3f+D0=" + package_id = pem.readBase64fromText(package_id_pem_text) + + self.assertEqual(package_id, kpe['errorOf']['pkgID']) + self.assertEqual( + rfc7191.EnumeratedErrorCode(value=10), kpe['errorCode']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.message3_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + v3 = rfc5652.CMSVersion().subtype(value='v3') + + self.assertEqual(v3, asn1Object['content']['version']) + + for sa in asn1Object['content']['signerInfos'][0]['signedAttrs']: + self.assertIn(sa['attrType'], rfc5652.cmsAttributesMap) + if sa['attrType'] == rfc5652.id_messageDigest: + self.assertIn( + '0xa05c54d4737', sa['attrValues'][0].prettyPrint()) + + ct_oid = asn1Object['content']['encapContentInfo']['eContentType'] + + self.assertIn(ct_oid, rfc5652.cmsContentTypesMap) + self.assertEqual(rfc7191.id_ct_KP_keyPackageError, ct_oid) + + # Since receipt is inside an OCTET STRING, decodeOpenTypes=True cannot + # automatically decode it + sd_eci = asn1Object['content']['encapContentInfo'] + kpe, rest = der_decoder( + sd_eci['eContent'], + asn1Spec=rfc5652.cmsContentTypesMap[sd_eci['eContentType']]) + package_id_pem_text = "J7icVjsWIlGdF4cceb+siG3f+D0=" + package_id = pem.readBase64fromText(package_id_pem_text) + + self.assertEqual(package_id, kpe['errorOf']['pkgID']) + self.assertEqual(rfc7191.EnumeratedErrorCode(value=10), kpe['errorCode']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc7229.py b/tests/test_rfc7229.py new file mode 100644 index 0000000..915b9be --- /dev/null +++ b/tests/test_rfc7229.py @@ -0,0 +1,93 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc7229 + + +class CertificatePolicyTestCase(unittest.TestCase): + pem_text = """\ +MIIDJDCCAqqgAwIBAgIJAKWzVCgbsG5AMAoGCCqGSM49BAMDMD8xCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9n +dXMgQ0EwHhcNMTkxMDEzMTkwNTUzWhcNMjAxMDEyMTkwNTUzWjBTMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xJTAjBgNVBAoTHFRF +U1QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AATwUXZUseiOaqWdrClDCMbp9YFAM87LTmFirygpzKDU9cfqSCg7zBDIphXCwMcS +9zVWDoStCbcvN0jw5CljHcffzpHYX91P88SZRJ1w4hawHjOsWxvM3AkYgZ5nfdlL +7EajggFcMIIBWDAdBgNVHQ4EFgQU8jXbNATapVXyvWkDmbBi7OIVCMEwbwYDVR0j +BGgwZoAU8jXbNATapVXyvWkDmbBi7OIVCMGhQ6RBMD8xCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0GC +CQDokdYGkU/O8jAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBhjBCBglghkgB +hvhCAQ0ENRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUgdHJ1c3RlZCBmb3Ig +YW55IHB1cnBvc2UuMCEGA1UdIAQaMBgwCgYIKwYBBQUHDQEwCgYIKwYBBQUHDQIw +CgYDVR02BAMCAQIwNQYDVR0hBC4wLDAUBggrBgEFBQcNAQYIKwYBBQUHDQcwFAYI +KwYBBQUHDQIGCCsGAQUFBw0IMAoGCCqGSM49BAMDA2gAMGUCMHaWskjS7MKQCMcn +zEKFOV3LWK8pL57vrECJd8ywKdwBJUNw9HhvSKkfUwL6rjlLpQIxAL2QO3CNoZRP +PZs8K3IjUA5+U73pA8lpaTOPscLY22WL9pAGmyVUyEJ8lM7E+r4iDg== +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + test_oids = [ + rfc7229.id_TEST_certPolicyOne, + rfc7229.id_TEST_certPolicyTwo, + rfc7229.id_TEST_certPolicyThree, + rfc7229.id_TEST_certPolicyFour, + rfc7229.id_TEST_certPolicyFive, + rfc7229.id_TEST_certPolicySix, + rfc7229.id_TEST_certPolicySeven, + rfc7229.id_TEST_certPolicyEight, + ] + + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + count = 0 + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] in rfc5280.certificateExtensionsMap.keys(): + s = extn['extnValue'] + ev, rest = der_decoder( + s, rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertFalse(rest) + self.assertTrue(ev.prettyPrint()) + self.assertEqual(s, der_encoder(ev)) + + if extn['extnID'] == rfc5280.id_ce_certificatePolicies: + for pol in ev: + if pol['policyIdentifier'] in test_oids: + count += 1 + + if extn['extnID'] == rfc5280.id_ce_policyMappings: + for pmap in ev: + if pmap['issuerDomainPolicy'] in test_oids: + count += 1 + if pmap['subjectDomainPolicy'] in test_oids: + count += 1 + + self.assertEqual(6, count) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc7292.py b/tests/test_rfc7292.py new file mode 100644 index 0000000..583d396 --- /dev/null +++ b/tests/test_rfc7292.py @@ -0,0 +1,183 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc7292 + + +class PKCS12TestCase(unittest.TestCase): + pfx_pem_text = """\ +MIIJ0wIBAzCCCY8GCSqGSIb3DQEHAaCCCYAEggl8MIIJeDCCBggGCSqGSIb3DQEHAaCCBfkE +ggX1MIIF8TCCBe0GCyqGSIb3DQEMCgECoIIE/jCCBPowHAYKKoZIhvcNAQwBAzAOBAjuq0/+ +0pyutQICB9AEggTYZe/mYBpmkDvKsve4EwIVwo1TNv4ldyx1qHZW2Ih6qQCY+Nv1Mnv9we0z +UTl4p3tQzCPWXnrSA82IgOdotLIez4YwXrgiKhcIkSSL+2yCmAoM+qkjiAIKq+l3UJ6Xhafe +2Kg4Ek/0RkHpe6GwjTtdefkpXpZgccMEopOtKQMLJWsDM7p77x/amn6yIk2tpskKqUY/4n8Y +xEiTWcRtTthYqZQIt+q94nKLYpt0o880SVOfvdEqp5KII7cTg60GJL+n6oN6hmP0bsAMvnk9 +1f8/lFKMi9tsNU/KnUhbDVpjJwBQkhgbqBx6GdtoqSLSlYNPVM0wlntwm1JhH4ybiQ5sNzqO +7FlWC5bcYwkvOlx1gGrshY5jK/WjbA4paBpxSkgobJReirY9BeqITnvokXlub4tehHhM20Ik +42pKa3kGaHmowvzflxqE+oysW5Oa9XbZxBCfkOMJ70o4hqa+n66+E/uKcN9NbKbTo3zt3xdt +6ypOwHb74t5OcWaGx3EZsw0n0/V+WoLSpXOBwpx08+1yh7LV29aNQ0oEzVVkF6YYRQZtdIMe +s3xB2i6sjLal21ntk7iBzMJwVoi524SAZ/oW8SuDAn1c93AWWwKZLALv5V3FZ2pDiQXArcfz +DH2d5HJyNx7OlvKzNgEngwSyEC1XbjnOsZVUqGFENuDTa/brH4oEJHEkyWTyDudrz8iCEO80 +e1PE4qqJ5CllN0CSVWqz4CxGDFIQXzR6ohn8f3dR3+DAaLYvAjBVMLJjk7+nfnB2L0HpanhT +Fz9AxPPIDf5pBQQwM14l8wKjEHIyfqclupeKNokBUr1ykioPyCr3nf4Rqe0Z4EKIY4OCpW6n +hrkWHmvF7OKR+bnuSk3jnBxjSN0Ivy5q9q3fntYrhscMGGR73umfi8Z29tM1vSP9jBZvirAo +geGf/sfOI0ewRvJf/5abnNg/78Zyk8WmlAHVFzNGcM3u3vhnNpTIVRuUyVkdSmOdbzeSfmqQ +2HPCEdC9HNm25KJt1pD6v6aP3Tw7qGl+tZyps7VB2i+a+UGcwQcClcoXcPSdG7Z1gBTzSr84 +MuVPYlePuo1x+UwppSK3rM8ET6KqhGmESH5lKadvs8vdT6c407PfLcfxyAGzjH091prk2oRJ +xB3oQAYcKvkuMcM6FSLJC263Dj+pe1GGEexk1AoysYe67tK0sB66hvbd92HcyWhW8/vI2/PM +bX+OeEb7q+ugnsP+BmF/btWXn9AxfUqNWstyInKTn+XpqFViMIOG4e2xC4u/IvzG3VrTWUHF +4pspH3k7GB/EOLvtbsR0uacBFlsColJy0FaWT9rrdueU3YEiIRCC8LGi1XpUa8f5adeBKWN+ +eRTrrF4o7uoNeGlnwZ7ebnb7k18Q0GRzzzTZPoMM4L703svfE/eNYWFHLY4NDQKSYgeum365 +WAfZpHOX7YOc6oRGrGB+QuGoyikTTDO8xpcEmb8vDz4ZwHhN0PS056LNJeMoI0A/5DJb3e10 +i1txlM48sbZBuIEIeixr52nwG4LuxqXGqShKaTfOrFxHjx4kI4/dp9dN/k8TGFsLWjuIgMJI +6nRHbWrxB3F0XKXagtLLep1MDwDwAuCyiW2YC0JzRvsJViIgjDA+eiHX0O6/8xiK9dzMQpIz +TVHSEqFlhORp0DGB2zATBgkqhkiG9w0BCRUxBgQEAQAAADBXBgkqhkiG9w0BCRQxSh5IADMA +ZgA3ADEAYQBmADYANQAtADEANgA4ADcALQA0ADQANABhAC0AOQBmADQANgAtAGMAOABiAGUA +MQA5ADQAYwAzAGUAOABlMGsGCSsGAQQBgjcRATFeHlwATQBpAGMAcgBvAHMAbwBmAHQAIABF +AG4AaABhAG4AYwBlAGQAIABDAHIAeQBwAHQAbwBnAHIAYQBwAGgAaQBjACAAUAByAG8AdgBp +AGQAZQByACAAdgAxAC4AMDCCA2gGCSqGSIb3DQEHAaCCA1kEggNVMIIDUTCCA00GCyqGSIb3 +DQEMCgEDoIIDJTCCAyEGCiqGSIb3DQEJFgGgggMRBIIDDTCCAwkwggHxoAMCAQICEDbt9oc6 +oQinRwE1826MiBEwDQYJKoZIhvcNAQEFBQAwFDESMBAGA1UEAxMJYW5vbnltb3VzMCAXDTE2 +MDcxOTIyMDAwMVoYDzIxMTYwNjI1MjIwMDAxWjAUMRIwEAYDVQQDEwlhbm9ueW1vdXMwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC8trBCTBjXXA4OgSO5nRTOU5T86ObCgc71 +J2oCuUigSddcTDzebaD0wcyAgf101hAdwMKQ9DvrK0nGvm7FAMnnUuVeATafKgshLuUTUUfK +jx4Xif4LoS0/ev4BiOI5a1MlIRZ7T5Cyjg8bvuympzMuinQ/j1RPLIV0VGU2HuDxuuP3O898 +GqZ3+F6Al5CUcwmOX9zCs91JdN/ZFZ05SXIpHQuyPSPUX5Vy8F1ZeJ8VG3nkbemfFlVkuKQq +vteL9mlT7z95rVZgGB3nUZL0tOB68eMcffA9zUksOmeTi5M6jnBcNeX2Jh9jS3YYd+IEliZm +mggQG7kPta8f+NqezL77AgMBAAGjVTBTMBUGA1UdJQQOMAwGCisGAQQBgjcKAwQwLwYDVR0R +BCgwJqAkBgorBgEEAYI3FAIDoBYMFGFub255bW91c0B3aW5kb3dzLXgAMAkGA1UdEwQCMAAw +DQYJKoZIhvcNAQEFBQADggEBALh+4qmNPzC6M8BW9/SC2ACQxxPh06GQUGx0D+GLYnp61ErZ +OtKyKdFh+uZWpu5vyYYAHCLXP7VdS/JhJy677ynAPjXiC/LAzrTNvGs74HDotD966Hiyy0Qr +ospFGiplHGRA5vXA2CiKSX+0HrVkN7rhk5PYkc6R+/cdosd+QZ8lkEa9yDWc5l//vWEbzwVy +mJf/PRf8NTkWAK6SPV7Y37j1mhkJjOH9VkRxNrd6kcihRa4u0ImXaXEsec77ER0so31DKCrP +m+rqZPj9NZSIYP3sMGJ4Bmm/n2YRdeaUzTdocfD3TRnKxs65DSgpiSq1gmtsXM7jAPs/Egrg +tbWEypgxFTATBgkqhkiG9w0BCRUxBgQEAQAAADA7MB8wBwYFKw4DAhoEFKVgj/32UdEyuQcB +rqr03dPnboinBBSU7mxdpB5LTCvorCI8Tk5OMiUzjgICB9A= +""" + + def setUp(self): + self.asn1Spec = rfc7292.PFX() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pfx_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(3, asn1Object['version']) + + oid = asn1Object['macData']['mac']['digestAlgorithm']['algorithm'] + + self.assertEqual(univ.ObjectIdentifier('1.3.14.3.2.26'), oid) + + md_hex = asn1Object['macData']['mac']['digest'].prettyPrint() + + self.assertEqual('0xa5608ffdf651d132b90701aeaaf4ddd3e76e88a7', md_hex) + self.assertEqual( + rfc5652.id_data, asn1Object['authSafe']['contentType']) + + data, rest = der_decoder( + asn1Object['authSafe']['content'], asn1Spec=univ.OctetString()) + + self.assertFalse(rest) + + authsafe, rest = der_decoder(data, asn1Spec=rfc7292.AuthenticatedSafe()) + + self.assertFalse(rest) + self.assertTrue(authsafe.prettyPrint()) + self.assertEqual(data, der_encoder(authsafe)) + + for ci in authsafe: + self.assertEqual(rfc5652.id_data, ci['contentType']) + + data, rest = der_decoder(ci['content'], asn1Spec=univ.OctetString()) + + self.assertFalse(rest) + + sc, rest = der_decoder(data, asn1Spec=rfc7292.SafeContents()) + + self.assertFalse(rest) + self.assertTrue(sc.prettyPrint()) + self.assertEqual(data, der_encoder(sc)) + + for sb in sc: + if sb['bagId'] in rfc7292.pkcs12BagTypeMap: + bv, rest = der_decoder( + sb['bagValue'], + asn1Spec=rfc7292.pkcs12BagTypeMap[sb['bagId']]) + + self.assertFalse(rest) + self.assertTrue(bv.prettyPrint()) + self.assertEqual(sb['bagValue'], der_encoder(bv)) + + for attr in sb['bagAttributes']: + if attr['attrType'] in rfc5652.cmsAttributesMap: + av, rest = der_decoder( + attr['attrValues'][0], + asn1Spec=rfc5652.cmsAttributesMap[attr['attrType']]) + self.assertFalse(rest) + self.assertTrue(av.prettyPrint()) + self.assertEqual( + attr['attrValues'][0], der_encoder(av)) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pfx_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + digest_alg = asn1Object['macData']['mac']['digestAlgorithm'] + + self.assertFalse(digest_alg['parameters'].hasValue()) + + authsafe, rest = der_decoder( + asn1Object['authSafe']['content'], + asn1Spec=rfc7292.AuthenticatedSafe(), + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(authsafe.prettyPrint()) + self.assertEqual( + asn1Object['authSafe']['content'], der_encoder(authsafe)) + + for ci in authsafe: + self.assertEqual(rfc5652.id_data, ci['contentType']) + sc, rest = der_decoder( + ci['content'], asn1Spec=rfc7292.SafeContents(), + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(sc.prettyPrint()) + self.assertEqual(ci['content'], der_encoder(sc)) + + for sb in sc: + if sb['bagId'] == rfc7292.id_pkcs8ShroudedKeyBag: + bv = sb['bagValue'] + enc_alg = bv['encryptionAlgorithm']['algorithm'] + self.assertEqual( + rfc7292.pbeWithSHAAnd3_KeyTripleDES_CBC, enc_alg) + enc_alg_param = bv['encryptionAlgorithm']['parameters'] + self.assertEqual(2000, enc_alg_param['iterations']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc7296.py b/tests/test_rfc7296.py new file mode 100644 index 0000000..4bc7577 --- /dev/null +++ b/tests/test_rfc7296.py @@ -0,0 +1,160 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc7296 + + +class CertBundleTestCase(unittest.TestCase): + cert_bundle_pem_text = """\ +MIITfqCCA8kwggPFMIICraADAgECAhACrFwmagtAm48LefKuRiV3MA0GCSqGSIb3 +DQEBBQUAMGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAX +BgNVBAsTEHd3dy5kaWdpY2VydC5jb20xKzApBgNVBAMTIkRpZ2lDZXJ0IEhpZ2gg +QXNzdXJhbmNlIEVWIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAw +MDAwWjBsMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD +VQQLExB3d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFz +c3VyYW5jZSBFViBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAxszlc+b71LvlLS0ypt/lgT/JzSVJtnEqw9WUNGeiChywX2mmQLHEt7KP0Jik +qUFZOtPclNY823Q4pErMTSWC90qlUxI47vNJbXGRfmO2q6Zfw6SE+E9iUb74xezb +OJLjBuUIkQzEKEFV+8taiRV+ceg1v01yCT2+OjhQW3cxG42zxyRFmqesbQAUWgS3 +uhPrUQqYQUEiTmVhh4FBUKZ5XIneGUpX1S7mXRxTLH6YzRoGFqRoc9A0BBNcoXHT +WnxV215k4TeHMFYE5RG0KYAS8Xk5iKICEXwnZreIt3jyygqoOKsKZMK/Zl2VhMGh +JR6HXRpQCyASzEG7bgtROLhLywIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUsT7DaQP4v0cB1JgmGggC72NkK8MwHwYD +VR0jBBgwFoAUsT7DaQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQEFBQADggEB +ABwaBpfc15yfPIhmBghXIdshR/gqZ6q/GDJ2QBBXwYrzetkRZY41+p78RbWe2Uwx +S7iR6EMsjrN4ztvjU3lx1uUhlAHaVYeaJGT2imbM3pw3zag0sWmbI8ieeCIrcEPj +VUcxYRnvWMWFL04w9qAxFiPI5+JlFjPLvxoboD34yl6LMYtgCIktDAZcUrfE+QqY +0RVfnxK+fDZjOL1EpH/kJisKxJdpDemM4sAQV7jIdhKRVfJIadi8KgJbD0TUIDHb +9LpwJl2QYJ68SxcJL7TLHkNoyQcnwdJc9+ohuWgSnDycv578gFybY83sR6olJ2eg +N/MAgn1U16n46S4To3foH0qgggS6MIIEtjCCA56gAwIBAgIQDHmpRLCMEZUgkmFf +4msdgzANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGln +aUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJE +aWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAw +MFoXDTI4MTAyMjEyMDAwMFowdTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lD +ZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTE0MDIGA1UEAxMrRGln +aUNlcnQgU0hBMiBFeHRlbmRlZCBWYWxpZGF0aW9uIFNlcnZlciBDQTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBANdTpARR+JmmFkhLZyeqk0nQOe0MsLAA +h/FnKIaFjI5j2ryxQDji0/XspQUYuD0+xZkXMuwYjPrxDKZkIYXLBxA0sFKIKx9o +m9KxjxKws9LniB8f7zh3VFNfgHk/LhqqqB5LKw2rt2O5Nbd9FLxZS99RStKh4gzi +kIKHaq7q12TWmFXo/a8aUGxUvBHy/Urynbt/DvTVvo4WiRJV2MBxNO723C3sxIcl +ho3YIeSwTQyJ3DkmF93215SF2AQhcJ1vb/9cuhnhRctWVyh+HA1BV6q3uCe7seT6 +Ku8hI3UarS2bhjWMnHe1c63YlC3k8wyd7sFOYn4XwHGeLN7x+RAoGTMCAwEAAaOC +AUkwggFFMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMB0GA1Ud +JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjA0BggrBgEFBQcBAQQoMCYwJAYIKwYB +BQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBLBgNVHR8ERDBCMECgPqA8 +hjpodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRIaWdoQXNzdXJhbmNl +RVZSb290Q0EuY3JsMD0GA1UdIAQ2MDQwMgYEVR0gADAqMCgGCCsGAQUFBwIBFhxo +dHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMB0GA1UdDgQWBBQ901Cl1qCt7vNK +YApl0yHU+PjWDzAfBgNVHSMEGDAWgBSxPsNpA/i/RwHUmCYaCALvY2QrwzANBgkq +hkiG9w0BAQsFAAOCAQEAnbbQkIbhhgLtxaDwNBx0wY12zIYKqPBKikLWP8ipTa18 +CK3mtlC4ohpNiAexKSHc59rGPCHg4xFJcKx6HQGkyhE6V6t9VypAdP3THYUYUN9X +R3WhfVUgLkc3UHKMf4Ib0mKPLQNa2sPIoc4sUqIAY+tzunHISScjl2SFnjgOrWNo +PLpSgVh5oywM395t6zHyuqB8bPEs1OG9d4Q3A84ytciagRpKkk47RpqF/oOi+Z6M +o8wNXrM9zwR4jxQUezKcxwCmXMS1oVWNWlZopCJwqjyBcdmdqEU79OX2olHdx3ti +6G8MdOu42vi/hw15UJGQmxg7kVkn8TUoE6smftX3eqCCB9wwggfYMIIGwKADAgEC +AhABW9pmX8RLdRe2iCweq9TcMA0GCSqGSIb3DQEBCwUAMHUxCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xNDAyBgNVBAMTK0RpZ2lDZXJ0IFNIQTIgRXh0ZW5kZWQgVmFsaWRhdGlvbiBT +ZXJ2ZXIgQ0EwHhcNMTgwODE0MDAwMDAwWhcNMjAwODE4MTIwMDAwWjCB3DEdMBsG +A1UEDwwUUHJpdmF0ZSBPcmdhbml6YXRpb24xEzARBgsrBgEEAYI3PAIBAxMCVVMx +GTAXBgsrBgEEAYI3PAIBAhMIRGVsYXdhcmUxEDAOBgNVBAUTBzMwMTQyNjcxCzAJ +BgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9z +ZTEVMBMGA1UEChMMUGF5UGFsLCBJbmMuMRQwEgYDVQQLEwtDRE4gU3VwcG9ydDEX +MBUGA1UEAxMOd3d3LnBheXBhbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDOofrgGYvXjVHH1WKEgxO51/bNk8Vw0WlZAyu0iwAUULZ3mrI8+xOw +gE5VGghgoQY9QNIA0mdFPrEmRRQAZXitszlL5s8oks4+tFzBHHtJp2D9BixRKxAR +Afo6c54tufaJUrQyIMwr2mpfbPox3palkK7RmHdimcOqtUjjQyS/WcHxMkyX3wa9 +e1JoEB9ofJGupNnC90uGgxilWLvOtn/27w56p2AYkKoSGgXsNRGE5ySxns23sZOo +tgSeTRe16K7X5JuzPcGtZGMRxlkVagZsrp8rNsf4aq0wKkBjkvVzSvJTaDJSDqEt +hV+ZoGSFYpwaHArVir0sJ63E/aq2Tb97AgMBAAGjggP6MIID9jAfBgNVHSMEGDAW +gBQ901Cl1qCt7vNKYApl0yHU+PjWDzAdBgNVHQ4EFgQUuzrmqCkAmIQyec538AFt +Xwp5Y7kwgaUGA1UdEQSBnTCBmoIOd3d3LnBheXBhbC5jb22CEmhpc3RvcnkucGF5 +cGFsLmNvbYIMdC5wYXlwYWwuY29tggxjLnBheXBhbC5jb22CDWM2LnBheXBhbC5j +b22CFGRldmVsb3Blci5wYXlwYWwuY29tggxwLnBheXBhbC5jb22CFXd3dy5wYXlw +YWxvYmplY3RzLmNvbYIOY21zLnBheXBhbC5jb20wDgYDVR0PAQH/BAQDAgWgMB0G +A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5o +dHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1ldi1zZXJ2ZXItZzIuY3JsMDSg +MqAwhi5odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1ldi1zZXJ2ZXItZzIu +Y3JsMEsGA1UdIAREMEIwNwYJYIZIAYb9bAIBMCowKAYIKwYBBQUHAgEWHGh0dHBz +Oi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwBwYFZ4EMAQEwgYgGCCsGAQUFBwEBBHww +ejAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFIGCCsGAQUF +BzAChkZodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEyRXh0 +ZW5kZWRWYWxpZGF0aW9uU2VydmVyQ0EuY3J0MAwGA1UdEwEB/wQCMAAwggF+Bgor +BgEEAdZ5AgQCBIIBbgSCAWoBaAB3AKS5CZC0GFgUh7sTosxncAo8NZgE+RvfuON3 +zQ7IDdwQAAABZTquQ3wAAAQDAEgwRgIhAMvZlCpgP2+v8gH82y3PQoMNVUVQNBjG +4DZy7qRFBo0JAiEAkzEfNkc2/B+88VR3QjutnaF1Qpj0QkSodPGAtB377UUAdQBW +FAaaL9fC7NP14b1Esj7HRna5vJkRXMDvlJhV1onQ3QAAAWU6rkPZAAAEAwBGMEQC +IHAvzbsYhbMy5jUazj6X3mDMjjyryN5BMwbDIFv58T9nAiBxzUIRTfj+Kevp0mmO +Oe9q6K/klOU2klRuVmcs7Gzw8AB2ALvZ37wfinG1k5Qjl6qSe0c4V5UKq1LoGpCW +ZDaOHtGFAAABZTquRGgAAAQDAEcwRQIhAMvzcJw5loOfVnDNFEr4+c4y/usA2pU5 +M7vhHND680tHAiASqPd7KXNaNTJsBJ9IfBN6J2XwGJjxccRy9fJc9+UgYjANBgkq +hkiG9w0BAQsFAAOCAQEAoeuef8cXLigvTQs4lbtbyp4UOIzspiMmHztqB95OS0ER +/u7995SO0C0mQjvyPeiptQ5Yh+/OVCqV6p2ZpBmSc+mn5tzjP3LaVxoyjwghja03 +mNBXPmdkEIG+V78Ov5iIm6vxGH1xSjHssV8iXpWo3gJ+xH3krtY1Atkg243JgwNC +I3xgp01VMLAmvIvvTqmIKeEd88Ukc6kHcZsEjxwtNivWx2nl1cyDu9B1wJK0D5Mu +IBXgbFKmqUhWlEXRimphvONOJGd71qT94bT/+bhq28oGleH1leTvqft0fj+e/a7e +Hx1u3fYAxNWjNAImIxpGUyUwSVo29w/CYYc2cS69y6GB7TCB6jCBqQIBATALBgcq +hkjOOAQDBQAwLjELMAkGA1UEBhMCdXMxDDAKBgNVBAoTA3N1bjERMA8GA1UEAxMI +aGFuZmVpeXUXDTA1MDEwNzIwMDkxMFoXDTA2MDEwNzIwMDkxMFowSTAjAgMBCTIX +DTA1MDEwNzIwMDkxMFowDTALBgNVHRUEBAoCAQQwIgICMDkXDTA1MDEwNzIwMDkx +MFowDTALBgNVHRUEBAoCAQEwCwYHKoZIzjgEAwUAAy8AMCwCFFbxw8qxTDJqc8H9 +O1QIkzwkkvJfAhRF5zFU8mFsrKmnE50ERySS8vA6AKGCAh8wggIbMIIBAwIBATAN +BgkqhkiG9w0BAQsFADBsMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQg +SW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2Vy +dCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBFw0xOTA1MDIyMjE1NTRaFw0xOTA1 +MjMyMjE1NTRaMDEwLwIQDPWCOBgZnlb4K9ZS7Sft6RcNMTgxMDI1MTYxMTM4WjAM +MAoGA1UdFQQDCgEAoDAwLjAfBgNVHSMEGDAWgBSxPsNpA/i/RwHUmCYaCALvY2Qr +wzALBgNVHRQEBAICAcQwDQYJKoZIhvcNAQELBQADggEBABPO3OA0OkQZ+RLVxz/c +Nx5uNVEO416oOePkN0A4DxFztf337caS4OyfS9Wyu1j5yUdWJVpAKXSQeN95MqHk +pSpYDssuqbuYjv8ViJfseGBgtXTczUzzNeNdY2uxMbCxuhmPkgacAo1lx9LkK2Sc +YHWVbfFRF1UQ/dcmavaZsEOBNuLWOxQYA9MqfVNAymHe7vPqwm/8IY2FbHe9HsiJ +ZfGxNWMDP5lmJiXmpntTeDQ2UjdiyXwGGKjyiSTFk2jVRutrGINufaoA/f7eCmIb +4UDPbpMjVfD215dW8eBKouypCVoEvmCSSTacdiBI2yOluvMN0PzvPve0ECAE+D4e +m9Y= +""" + + def setUp(self): + self.asn1Spec = rfc7296.CertificateBundle() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.cert_bundle_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + cert_count = 0 + crl_count = 0 + unk_count = 0 + + for item in asn1Object: + if item.getName() == 'cert': + cert_count += 1 + + elif item.getName() == 'crl': + crl_count += 1 + + else: + unk_count += 1 + + self.assertEqual(3, cert_count) + self.assertEqual(2, crl_count) + self.assertEqual(0, unk_count) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc7508.py b/tests/test_rfc7508.py new file mode 100644 index 0000000..914e6d8 --- /dev/null +++ b/tests/test_rfc7508.py @@ -0,0 +1,134 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc7508 + + +class SignedMessageTestCase(unittest.TestCase): + signed_message_pem_text = """\ +MIIE/AYJKoZIhvcNAQcCoIIE7TCCBOkCAQExDTALBglghkgBZQMEAgIwUQYJKoZI +hvcNAQcBoEQEQkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbg0KDQpXYXRzb24sIGNv +bWUgaGVyZSAtIEkgd2FudCB0byBzZWUgeW91LqCCAnwwggJ4MIIB/qADAgECAgkA +pbNUKBuwbjswCgYIKoZIzj0EAwMwPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZB +MRAwDgYDVQQHDAdIZXJuZG9uMREwDwYDVQQKDAhCb2d1cyBDQTAeFw0xOTA1Mjkx +NDQ1NDFaFw0yMDA1MjgxNDQ1NDFaMHAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJW +QTEQMA4GA1UEBxMHSGVybmRvbjEQMA4GA1UEChMHRXhhbXBsZTEOMAwGA1UEAxMF +QWxpY2UxIDAeBgkqhkiG9w0BCQEWEWFsaWNlQGV4YW1wbGUuY29tMHYwEAYHKoZI +zj0CAQYFK4EEACIDYgAE+M2fBy/sRA6V1pKFqecRTE8+LuAHtZxes1wmJZrBBg+b +z7uYZfYQxI3dVB0YCSD6Mt3yXFlnmfBRwoqyArbjIBYrDbHBv2k8Csg2DhQ7qs/w +to8hMKoFgkcscqIbiV7Zo4GUMIGRMAsGA1UdDwQEAwIHgDBCBglghkgBhvhCAQ0E +NRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUgdHJ1c3RlZCBmb3IgYW55IHB1 +cnBvc2UuMB0GA1UdDgQWBBTEuloOPnrjPIGw9AKqaLsW4JYONTAfBgNVHSMEGDAW +gBTyNds0BNqlVfK9aQOZsGLs4hUIwTAKBggqhkjOPQQDAwNoADBlAjBjuR/RNbgL +3kRhmn+PJTeKaL9sh/oQgHOYTgLmSnv3+NDCkhfKuMNoo/tHrkmihYgCMQC94Mae +rDIrQpi0IDh+v0QSAv9rMife8tClafXWtDwwL8MS7oAh0ymT446Uizxx3PUxggIA +MIIB/AIBATBMMD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwH +SGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0ECCQCls1QoG7BuOzALBglghkgBZQME +AgKgggElMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8X +DTE5MDUyOTE4MjMxOVowKAYJKoZIhvcNAQk0MRswGTALBglghkgBZQMEAgKhCgYI +KoZIzj0EAwMwMQYLKoZIhvcNAQkQAjcxIjEgCgEBMBswGRoERnJvbQwRYWxpY2VA +ZXhhbXBsZS5jb20wPwYJKoZIhvcNAQkEMTIEMLbkIqT9gmce1Peqxm1E9OiwuY1R +WHHGVufwmjb6XKzj4goQ5tryN5uJN9NM+ZkmbDBNBgsqhkiG9w0BCRACATE+MDwE +IMdPIQ9kJ1cI9Q6HkRCzbXWdD331uAUCL3MMFXP4KFOjgAEBMBUwE4ERYWxpY2VA +ZXhhbXBsZS5jb20wCgYIKoZIzj0EAwMEZzBlAjEAuZ8SebvwMRvLPn9+s3VHFUNU +bEtkkWCao1uNm5TOzphK0NbxzOsD854aC5ReKPSDAjAm1U0siLQw5p4qzGwyxDw9 +5AI5J8Mvy+icNubmfsd4ofvxdaECdhr4rvsSMwbOsFk= +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.signed_message_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + secure_header_field_attr_found = False + + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + sd, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.SignedData()) + + for sa in sd['signerInfos'][0]['signedAttrs']: + sat = sa['attrType'] + sav0 = sa['attrValues'][0] + + if sat == rfc7508.id_aa_secureHeaderFieldsIdentifier: + self.assertIn(sat, rfc5652.cmsAttributesMap) + sav, rest = der_decoder( + sav0, asn1Spec=rfc5652.cmsAttributesMap[sat]) + + self.assertFalse(rest) + self.assertTrue(sav.prettyPrint()) + self.assertEqual(sav0, der_encoder(sav)) + + from_field = rfc7508.HeaderFieldName('From') + alice_email = rfc7508.HeaderFieldValue('alice@example.com') + for shf in sav['secHeaderFields']: + if shf['field-Name'] == from_field: + self.assertEqual(alice_email, shf['field-Value']) + secure_header_field_attr_found = True + + self.assertTrue(secure_header_field_attr_found) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.signed_message_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertIn(asn1Object['contentType'], rfc5652.cmsContentTypesMap) + self.assertEqual(asn1Object['contentType'], rfc5652.id_signedData) + + sd = asn1Object['content'] + + self.assertEqual( + rfc5652.CMSVersion().subtype(value='v1'), sd['version']) + + ect = sd['encapContentInfo']['eContentType'] + + self.assertIn(ect, rfc5652.cmsContentTypesMap) + self.assertEqual(rfc5652.id_data, ect) + + for sa in sd['signerInfos'][0]['signedAttrs']: + if sa['attrType'] == rfc7508.id_aa_secureHeaderFieldsIdentifier: + self.assertIn(sa['attrType'], rfc5652.cmsAttributesMap) + + secure_header_field_attr_found = False + for sa in sd['signerInfos'][0]['signedAttrs']: + if sa['attrType'] == rfc7508.id_aa_secureHeaderFieldsIdentifier: + self.assertIn(sa['attrType'], rfc5652.cmsAttributesMap) + from_field = rfc7508.HeaderFieldName('From') + alice_email = rfc7508.HeaderFieldValue('alice@example.com') + for shf in sa['attrValues'][0]['secHeaderFields']: + if shf['field-Name'] == from_field: + self.assertEqual(alice_email, shf['field-Value']) + secure_header_field_attr_found = True + + self.assertTrue(secure_header_field_attr_found) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc7585.py b/tests/test_rfc7585.py new file mode 100644 index 0000000..5e53834 --- /dev/null +++ b/tests/test_rfc7585.py @@ -0,0 +1,126 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc7585 + + +class NAIRealmCertTestCase(unittest.TestCase): + cert_pem_text = """\ +MIIEZzCCA0+gAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBkjELMAkGA1UEBhMCRlIx +DzANBgNVBAgMBlJhZGl1czESMBAGA1UEBwwJU29tZXdoZXJlMRQwEgYDVQQKDAtF +eGFtcGxlIEluYzEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBsZS5vcmcxJjAk +BgNVBAMMHUV4YW1wbGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTE5MTExMTE4 +MDQyMVoXDTIwMDExMDE4MDQyMVowezELMAkGA1UEBhMCRlIxDzANBgNVBAgMBlJh +ZGl1czEUMBIGA1UECgwLRXhhbXBsZSBJbmMxIzAhBgNVBAMMGkV4YW1wbGUgU2Vy +dmVyIENlcnRpZmljYXRlMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLm9y +ZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM9HqbuyWpsTMKo739Dm +DwmQo2HUkNdQYbvsB+e7ILsw8fWa2qnsF1CoRr/1bcZqXUR1To/QbHse7xSMZH9t +F7rdlDMc7QtgdwVfn8TiL3hCg5LSE8iaBzfJUjrts/V5WOByP1DwJVM7W3Va/5dN +oOiceVeC7ThghMlwIx/wN5cy78a8fPYV2FvPR6e+U2HG35zaIv2PizYcliF/QmZG +gnw4Q9dYC1Lw/ogVBZBALlv+/MuGheb/xIuL8lu1PFZ0YbW65WLD9Cx4wvytAke7 +tKlhL/Kd4OBSeOY3OYmpxbc1gEUmFoLTlZesY2NP9Jyl5mGsIHtPdvVkh/tSBy8o +VLUCAwEAAaOB3TCB2jAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DATBgNVHSUEDDAK +BggrBgEFBQcDATA2BgNVHR8ELzAtMCugKaAnhiVodHRwOi8vd3d3LmV4YW1wbGUu +Y29tL2V4YW1wbGVfY2EuY3JsMDcGCCsGAQUFBwEBBCswKTAnBggrBgEFBQcwAYYb +aHR0cDovL3d3dy5leGFtcGxlLm9yZy9vY3NwMDoGA1UdEQQzMDGCEnJhZGl1cy5l +eGFtcGxlLm9yZ6AbBggrBgEFBQcICKAPDA0qLmV4YW1wbGUuY29tMA0GCSqGSIb3 +DQEBCwUAA4IBAQBOhtH2Jpi0b0MZ8FBKTqDl44rIHL1rHG2mW/YYmRI4jZo8kFhA +yWm/T8ZpdaotJgRqbQbeXvTXIg4/JNFheyLG4yLOzS1esdMAYDD5EN9/dXE++jND +/wrfPU+QtTgzAjkgFDKuqO7gr1/vSizxLYTWLKBPRHhiQo7GGlEC6/CPb38x4mfQ +5Y9DsKCp6BEZu+LByCho/HMDzcIPCdtXRX7Fs8rtX4/zRpVIdm6D+vebuo6CwRKp +mIljfssCvZjb9YIxSVDmA/6Lapqsfsfo922kb+MTXvPrq2ynPx8LrPDrxKc8maYc +Jiw8B0yjkokwojxyRGftMT8uxNjWQVsMDbxl +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + nai_realm_oid = rfc7585.id_on_naiRealm + nai_realm_found = False + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectAltName: + extnValue, rest = der_decoder( + extn['extnValue'], asn1Spec=rfc5280.SubjectAltName()) + + self.assertFalse(rest) + self.assertTrue(extnValue.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + for gn in extnValue: + if gn['otherName'].hasValue(): + self.assertEqual( + nai_realm_oid, gn['otherName']['type-id']) + + onValue, rest = der_decoder( + gn['otherName']['value'], asn1Spec=rfc7585.NAIRealm()) + + self.assertFalse(rest) + self.assertTrue(onValue.prettyPrint()) + self.assertEqual( + gn['otherName']['value'], der_encoder(onValue)) + self.assertIn('example', onValue) + + nai_realm_found = True + + self.assertTrue(nai_realm_found) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + nai_realm_oid = rfc7585.id_on_naiRealm + nai_realm_found = False + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] == rfc5280.id_ce_subjectAltName: + extnValue, rest = der_decoder( + extn['extnValue'], asn1Spec=rfc5280.SubjectAltName(), + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(extnValue.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + for gn in extnValue: + if gn['otherName'].hasValue(): + self.assertEqual( + nai_realm_oid, gn['otherName']['type-id']) + self.assertIn('example', gn['otherName']['value']) + + nai_realm_found = True + + self.assertTrue(nai_realm_found) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc7633.py b/tests/test_rfc7633.py new file mode 100644 index 0000000..64e874e --- /dev/null +++ b/tests/test_rfc7633.py @@ -0,0 +1,80 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc7633 + + +class TLSFeaturesExtnTestCase(unittest.TestCase): + pem_text = """\ +MIIEbTCCBBOgAwIBAgIRAO5f2N8q74GBATjTMXQCjlgwCgYIKoZIzj0EAwIwgZYx +CzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNV +BAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTwwOgYDVQQD +EzNDT01PRE8gRUNDIE9yZ2FuaXphdGlvbiBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2 +ZXIgQ0EwHhcNMTYwMTE1MDAwMDAwWhcNMTgwMTE0MjM1OTU5WjCBwjELMAkGA1UE +BhMCUlUxDzANBgNVBBETBjExNzY0NzEUMBIGA1UECBMLTW9zY293IENpdHkxDzAN +BgNVBAcTBk1vc2NvdzE4MDYGA1UECRMvQWthZGVtaWthIEthcGljeSBzdHJlZXQs +IGhvdXNlIDQsIGFwYXJ0bWVudCAxNjYxGDAWBgNVBAoTD0FuZHJleSBDaHVyYW5v +djETMBEGA1UECxMKSW5zdGFudFNTTDESMBAGA1UEAxMJYWRtc2VsLmVjMHYwEAYH +KoZIzj0CAQYFK4EEACIDYgAEwrPPzgBO1vDNmV0UVvYSBnys9B7LVkGLiIBbKYf2 +nNFRuJKo1gzNurI8pv4CbvqjkCX4Je/aSeYFHSCR9y82+zTwYQuJFt5LIL5f+Syp +xZ7aLH56bOiQ+QhCtIvWP4YWo4IB9TCCAfEwHwYDVR0jBBgwFoAUdr4iSO4/PvZG +A9mHGNBlfiKcC+EwHQYDVR0OBBYEFHTFQqV+H5a7+RVL+70Z6zqCbqq9MA4GA1Ud +DwEB/wQEAwIFgDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggr +BgEFBQcDAjBQBgNVHSAESTBHMDsGDCsGAQQBsjEBAgEDBDArMCkGCCsGAQUFBwIB +Fh1odHRwczovL3NlY3VyZS5jb21vZG8uY29tL0NQUzAIBgZngQwBAgIwWgYDVR0f +BFMwUTBPoE2gS4ZJaHR0cDovL2NybC5jb21vZG9jYS5jb20vQ09NT0RPRUNDT3Jn +YW5pemF0aW9uVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNybDCBiwYIKwYBBQUH +AQEEfzB9MFUGCCsGAQUFBzAChklodHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9DT01P +RE9FQ0NPcmdhbml6YXRpb25WYWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3J0MCQG +CCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wEQYIKwYBBQUHARgE +BTADAgEFMCMGA1UdEQQcMBqCCWFkbXNlbC5lY4INd3d3LmFkbXNlbC5lYzAKBggq +hkjOPQQDAgNIADBFAiAi6TXl76FTKPP1AhqtEjU5BjAj9Ju7CSKChHZSmzxeXQIh +AOQSxhs011emVxyBIXT0ZGbmBY8LFRh6eGIOCAJbkM5T +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + extn_list = [] + + for extn in asn1Object['tbsCertificate']['extensions']: + extn_list.append(extn['extnID']) + if extn['extnID'] == rfc7633.id_pe_tlsfeature: + s = extn['extnValue'] + features, rest = der_decoder( + s, rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertFalse(rest) + self.assertTrue(features.prettyPrint()) + self.assertEqual(s, der_encoder(features)) + self.assertEqual(1, len(features)) + self.assertEqual(5, features[0]) + + self.assertIn(rfc7633.id_pe_tlsfeature, extn_list) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc7773.py b/tests/test_rfc7773.py new file mode 100644 index 0000000..2b4e50b --- /dev/null +++ b/tests/test_rfc7773.py @@ -0,0 +1,113 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc7773 + + +class AuthenticationContextExtnTestCase(unittest.TestCase): + pem_text = """\ +MIIMUjCCCzqgAwIBAgIQevDaX+wRYAlpUgjTYjCCRjANBgkqhkiG9w0BAQsFADCBuDELMAkGA1UE +BhMCU0UxNTAzBgNVBAoTLERldiBURVNUIENBIG9yZyBBQiAoTk9UIEEgUkVBTCBPUkdBTklaQVRJ +T04pMSAwHgYDVQQLExdDZW50cmFsIFNpZ25pbmcgU2VydmljZTEVMBMGA1UEBRMMQTEyMzQ1Ni03 +ODkwMTkwNwYDVQQDEzBDZW50cmFsIFNpZ25pbmcgQ0EwMDEgLSBFSUQgMi4wIERldiBURVNUIFNl +cnZpY2UwHhcNMTkxMDA5MDc0ODI2WhcNMjAxMDA5MDc0ODI2WjBgMRUwEwYDVQQFEwwxODg4MDMw +OTkzNjgxCzAJBgNVBAYTAlNFMQ0wCwYDVQQqEwRBZ2RhMRcwFQYDVQQDEw5BZ2RhIEFuZGVyc3Nv +bjESMBAGA1UEBBMJQW5kZXJzc29uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjl1H +7vveI/EUaF9z6EiL/AmTHDbpLAKoWh9JJjpRlb8lU0TseYOzZp6ySiAO8St2a/HxxhrNuAAELUwZ +3oICkmxM/NeYgI7EEaLVPUwBAWfGZrRWb/+h8C6SrivWc73M/LI1A0B9tcEpUuh0CHTSVIBZsH+L +IDyKW6n3T8YeI7+0CX391I/j3iyEBNFcfDaHaFChzkPxgPg6Xh1D1JWs+mUj1rOoTLxsyusWiIQk +IkjDgFNUCpS1+NUvkTU1uFewvluxjOzRVqzYZWesOL+V/lGnyVPw4o1INEKYpOurYii2TXElTmXO +iQdIG20S96uFH6vFFJ2cPwgYjWpory/K+QIDAQABo4IIrTCCCKkwCwYDVR0PBAQDAgZAMB0GA1Ud +DgQWBBQo71oFnxX2kapLl3ZoYOylnJo01TATBgNVHSAEDDAKMAgGBgQAizABATBLBgNVHR8ERDBC +MECgPqA8hjpodHRwczovL2VpZDJjc2lnLmtvbmtpLnNlL3B1Ymxpc2gvY3JsLzE4MTRiMGFiYzEx +NGM3YmEuY3JsMIIH6wYHKoVwgUkFAQSCB94wggfaMIIH1gwraHR0cDovL2lkLmVsZWduYW1uZGVu +LnNlL2F1dGgtY29udC8xLjAvc2FjaQyCB6U8c2FjaTpTQU1MQXV0aENvbnRleHQgeG1sbnM6c2Fj +aT0iaHR0cDovL2lkLmVsZWduYW1uZGVuLnNlL2F1dGgtY29udC8xLjAvc2FjaSI+PHNhY2k6QXV0 +aENvbnRleHRJbmZvIElkZW50aXR5UHJvdmlkZXI9Imh0dHA6Ly9kZXYudGVzdC5zd2VkZW5jb25u +ZWN0LnNlL2lkcCIgQXV0aGVudGljYXRpb25JbnN0YW50PSIyMDE5LTEwLTA5VDA3OjU4OjI2LjAw +MFoiIFNlcnZpY2VJRD0iRmVkU2lnbmluZyIgQXV0aG5Db250ZXh0Q2xhc3NSZWY9Imh0dHA6Ly9p +ZC5lbGVnbmFtbmRlbi5zZS9sb2EvMS4wL2xvYTMtc2lnbWVzc2FnZSIgQXNzZXJ0aW9uUmVmPSJf +ZGM5MjM0Y2Y3Zjc5OWQwMDlmMjUwNWVhMzVlMWU0NmUiLz48c2FjaTpJZEF0dHJpYnV0ZXM+PHNh +Y2k6QXR0cmlidXRlTWFwcGluZyBUeXBlPSJyZG4iIFJlZj0iMi41LjQuNSI+PHNhbWw6QXR0cmli +dXRlIEZyaWVuZGx5TmFtZT0iU3dlZGlzaCBQZXJzb25udW1tZXIiIE5hbWU9InVybjpvaWQ6MS4y +Ljc1Mi4yOS40LjEzIiB4bWxuczpzYW1sPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNz +ZXJ0aW9uIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIiB4bWxuczp4 +cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3 +dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiPjE4ODgwMzA5OTM2ODwvc2FtbDpBdHRy +aWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjwvc2FjaTpBdHRyaWJ1dGVNYXBwaW5nPjxzYWNp +OkF0dHJpYnV0ZU1hcHBpbmcgVHlwZT0icmRuIiBSZWY9IjIuNS40LjQyIj48c2FtbDpBdHRyaWJ1 +dGUgRnJpZW5kbHlOYW1lPSJHaXZlbiBOYW1lIiBOYW1lPSJ1cm46b2lkOjIuNS40LjQyIiB4bWxu +czpzYW1sPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj48c2FtbDpBdHRy +aWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIiB4bWxuczp4cz0iaHR0cDovL3d3dy53My5v +cmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxT +Y2hlbWEtaW5zdGFuY2UiPkFnZGE8L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0 +ZT48L3NhY2k6QXR0cmlidXRlTWFwcGluZz48c2FjaTpBdHRyaWJ1dGVNYXBwaW5nIFR5cGU9InJk +biIgUmVmPSIyLjUuNC4zIj48c2FtbDpBdHRyaWJ1dGUgRnJpZW5kbHlOYW1lPSJEaXNwbGF5IE5h +bWUiIE5hbWU9InVybjpvaWQ6Mi4xNi44NDAuMS4xMTM3MzAuMy4xLjI0MSIgeG1sbnM6c2FtbD0i +dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiI+PHNhbWw6QXR0cmlidXRlVmFs +dWUgeHNpOnR5cGU9InhzOnN0cmluZyIgeG1sbnM6eHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEv +WE1MU2NoZW1hIiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWlu +c3RhbmNlIj5BZ2RhIEFuZGVyc3Nvbjwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmli +dXRlPjwvc2FjaTpBdHRyaWJ1dGVNYXBwaW5nPjxzYWNpOkF0dHJpYnV0ZU1hcHBpbmcgVHlwZT0i +cmRuIiBSZWY9IjIuNS40LjQiPjxzYW1sOkF0dHJpYnV0ZSBGcmllbmRseU5hbWU9IlN1cm5hbWUi +IE5hbWU9InVybjpvaWQ6Mi41LjQuNCIgeG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRjOlNB +TUw6Mi4wOmFzc2VydGlvbiI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmlu +ZyIgeG1sbnM6eHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hIiB4bWxuczp4c2k9 +Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIj5BbmRlcnNzb248L3Nh +bWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48L3NhY2k6QXR0cmlidXRlTWFwcGlu +Zz48L3NhY2k6SWRBdHRyaWJ1dGVzPjwvc2FjaTpTQU1MQXV0aENvbnRleHQ+MAkGA1UdEwQCMAAw +HwYDVR0jBBgwFoAUqKv0QPwAYcLfcD/Vy1A2deHtiqcwDQYJKoZIhvcNAQELBQADggEBAETlZOIL +NknxlMiYHCxoYypyzYuza2l3M4+YWakT0vFPgXpCk+l0dNst7h9nWvKKHCboSj+YP5dUCSsuUXhb +7xTei/F2nj7q1oCPuVJGThZqhWgF/JkqOy34hHEM5VniJiQu2W9TjzRMSOSFzRlQsHcOuXzdTkhr +CQpD1TWxYL9sCy4YoCdE4edfgBGBMujxoijl3/xJ5uI1FjhlSPVP88p8Wsi8i7GdMYuxqjZMwrt2 +PHIPgop3BNN9/BzW0cmdyNvFgcD9qR8Rv5aFBYuQbyg6fST8JdAOrbMrCST6v2U41OOXH5MC/kL6 +tAGXsYdcuQpglUngmo/FV4Z9qjIDkYQ= +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + extn_list = [] + + for extn in asn1Object['tbsCertificate']['extensions']: + extn_list.append(extn['extnID']) + + if extn['extnID'] == rfc7773.id_ce_authContext: + s = extn['extnValue'] + acs, rest = der_decoder( + s, asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + self.assertFalse(rest) + self.assertTrue(acs.prettyPrint()) + self.assertEqual(s, der_encoder(acs)) + self.assertIn('id.elegnamnden.se', acs[0]['contextType']) + self.assertIn( + 'AuthContextInfo IdentityProvider', acs[0]['contextInfo']) + + self.assertIn(rfc7773.id_ce_authContext, extn_list) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc7894.py b/tests/test_rfc7894.py new file mode 100644 index 0000000..3d38155 --- /dev/null +++ b/tests/test_rfc7894.py @@ -0,0 +1,84 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc6402 +from pyasn1_modules import rfc7894 + + +class AlternativeChallengePasswordTestCase(unittest.TestCase): + otp_pem_text = """\ +MIICsjCCAZwCAQAwJDELMAkGA1UEBhMCVVMxFTATBgNVBAMTDDRUUzJWMk5MWEE2 +WjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKmF0oUj5+1rBB+pUO8X +7FPxer+1BhWOa54RTSucJmBaLx0H95qNaBCcctNDl1kcmIro/a0zMcEvj5Do29vQ +lStJdTeJ/B3X4qzOGShupxJcAhCreRZjN6Yz3T9z0zJ8OPnRvJOzcSiIzlubc9lK +Cpq4U0UsCLLfymOgL9NH4lZi96J+PFuJr0J+rTY38076U2jcPqNq5/L/d6NV9Sz2 +IVOvCK1kqP/nElJVibIQZvj9YESLUKyVAfTNxLj3+IpioOOv2dT3kB9wdi4plAVi +UFEUvED1okRrI29+LdPV1UXglOCksyJIIw+DgDtutDE5Co6QkTNURFEdKIV9Sg13 +zEECAwEAAaBLMBkGCyqGSIb3DQEJEAI4MQoTCDkwNTAzODQ2MC4GCSqGSIb3DQEJ +DjEhMB8wHQYDVR0OBBYEFBj12LVowM16Ed0D+AmoElKNYP/kMAsGCSqGSIb3DQEB +CwOCAQEAZZdDWKejs3UVfgZI3R9cMWGijmscVeZrjwFVkn7MI9pEDZ2aS1QaRYjY +1cu9j3i+LQp9LWPIW/ztYk11e/OcZp3fo8pZ+MT66n7YTWfDXNkqqA5xmI84DMEx +/cqenyzOBZWqpZGx7eyM9BtnrdeJ0r2qSc7LYU25FbIQFJJf8IvgMAXWMs50fvs2 +Gzns447x952se2ReQ3vYhXdHvYYcgAZfSJZvK+nCmhzzqowv5p15Y5S+IHpBSXTO +a1qhNW4cjdicQZUeQ2R5kiuwZ+8vHaq9jKxAEk0hBeqG6RQaxvNOBQhHtTLNGw/C +NmaF8Y2Sl/MgvC5tjs0Ck0/r3lsoLQ== +""" + + def setUp(self): + self.asn1Spec = rfc6402.CertificationRequest() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.otp_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(0, asn1Object['certificationRequestInfo']['version']) + + for attr in asn1Object['certificationRequestInfo']['attributes']: + self.assertIn( + attr['attrType'], rfc6402.cmcControlAttributesMap) + + av, rest = der_decoder( + attr['attrValues'][0], + rfc6402.cmcControlAttributesMap[attr['attrType']]) + + self.assertFalse(rest) + self.assertEqual(attr['attrValues'][0], der_encoder(av)) + + if attr['attrType'] == rfc7894.id_aa_otpChallenge: + self.assertEqual('90503846', av['printableString']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.otp_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + for attr in asn1Object['certificationRequestInfo']['attributes']: + self.assertIn(attr['attrType'], rfc6402.cmcControlAttributesMap) + if attr['attrType'] == rfc7894.id_aa_otpChallenge: + self.assertEqual( + '90503846', attr['attrValues'][0]['printableString']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc7906.py b/tests/test_rfc7906.py new file mode 100644 index 0000000..3806987 --- /dev/null +++ b/tests/test_rfc7906.py @@ -0,0 +1,168 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc2985 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc7906 + + +class AttributeSetTestCase(unittest.TestCase): + attr_set_pem_text = """\ +MYIRmDAQBglghkgBZQIBDQcxA4IBATAQBglghkgBZQIBDQ0xAwoBUzAQBglghkgB +ZQIBDQ4xAwoBAjAQBglghkgBZQIBDQ8xAwoBATARBglghkgBZQIBBUIxBAQCeQYw +EgYJYIZIAWUCAQ0LMQUwAwoBATAVBglghkgBZQIBDQUxCDAGAgReAA//MBUGCyqG +SIb3DQEJEAIuMQYCBF1qowYwGQYJYIZIAWUCAQVHMQwGCisGAQQBgaxgME0wGgYJ +YIZIAWUCAQ0BMQ0wCwYJYIZIAWUDBAEtMBoGCWCGSAFlAgENDDENBgsqhkiG9w0B +CRABGTAaBglghkgBZQIBDRUxDTALBglghkgBZQMEAS0wGwYJYIZIAWUCAQ0GMQ4w +DAIEXQAAAAIEXwAP/zAdBgsqhkiG9w0BCRACKDEOMAwGCisGAQQBgaxgMDAwLQYJ +YIZIAWUCAQVGMSAwHoYcaHR0cDovL3JlcG8uZXhhbXBsZS5jb20vcGtpLzAvBglg +hkgBZQIBDQMxIjAgExFCb2d1cyBTaG9ydCBUaXRsZYEFQm9ndXOFATCHAU0wNAYJ +YIZIAWUCAQVIMScwJRMRQm9ndXMgU2hvcnQgVGl0bGUTEEZha2UgU2hvcnQgVGl0 +bGUwOAYIKwYBBQUHAQsxLDAqMCgGCCsGAQUFBzAFhhxodHRwOi8vcmVwby5leGFt +cGxlLmNvbS9wa2kvMEEGCyqGSIb3DQEJEAIEMTIwMAwjVGhlc2UgUkZDIDc5MDYg +YXR0cmlidXRlcyBhcmUgYm9ndXMGCSqGSIb3DQEHATCBggYLKoZIhvcNAQkQAgIx +czFxAgEBBgorBgEEAYGsYAEBMUwwJIAKYIZIAWUCAQgDA4EWMBQGCisGAQQBgaxg +MEkxBgIBMAIBSTAkgApghkgBZQIBCAMEgRYwFAYKKwYBBAGBrGAwRTEGAgEwAgFF +ExJCb2d1cyBQcml2YWN5IE1hcmswgYQGCWCGSAFlAgENFjF3MHUwMAYKYIZIAWUC +AQJOAjAiMCAGCyqGSIb3DQEJEAwLMREMD2t0YS5leGFtcGxlLmNvbTAxBgsqhkiG +9w0BCRABGTAiMCAGCyqGSIb3DQEJEAwLMREMD2t0YS5leGFtcGxlLmNvbTAOBgkq +hkiG9w0BBwEKAQEwgaAGCWCGSAFlAgENEDGBkjCBj6EMBgorBgEEAYGsYDAwoH8G +CWCGSAFlAgEQAARyMHAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJWQTEQMA4GA1UE +BxMHSGVybmRvbjEQMA4GA1UEChMHRXhhbXBsZTEOMAwGA1UEAxMFQWxpY2UxIDAe +BgkqhkiG9w0BCQEWEWFsaWNlQGV4YW1wbGUuY29tMIIBvwYJYIZIAWUCAQVBMYIB +sDCCAawEFO1lDTbJmd4voc2GDuaMzYO+XJSmMIIBkqCB/jB/BglghkgBZQIBEAAE +cjBwMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24x +EDAOBgNVBAoTB0V4YW1wbGUxDjAMBgNVBAMTBUFsaWNlMSAwHgYJKoZIhvcNAQkB +FhFhbGljZUBleGFtcGxlLmNvbTB7BglghkgBZQIBEAAEbjBsMQswCQYDVQQGEwJV +UzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xEDAOBgNVBAoTB0V4YW1w +bGUxDDAKBgNVBAMTA0JvYjEeMBwGCSqGSIb3DQEJARYPYm9iQGV4YW1wbGUuY29t +MIGOMIGLBglghkgBZQIBEAAEfjB8MQswCQYDVQQGEwJVUzELMAkGA1UECBMCVkEx +EDAOBgNVBAcTB0hlcm5kb24xGzAZBgNVBAoTElZpZ2lsIFNlY3VyaXR5IExMQzEX +MBUGA1UECxMOS2V5IE1hbmFnZW1lbnQxGDAWBgNVBAMTD2t0YS5leGFtcGxlLmNv +bTCCAoUGA1UEJDGCAnwwggJ4MIIB/qADAgECAgkApbNUKBuwbjswCgYIKoZIzj0E +AwMwPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMRAwDgYDVQQHDAdIZXJuZG9u +MREwDwYDVQQKDAhCb2d1cyBDQTAeFw0xOTA1MjkxNDQ1NDFaFw0yMDA1MjgxNDQ1 +NDFaMHAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJWQTEQMA4GA1UEBxMHSGVybmRv +bjEQMA4GA1UEChMHRXhhbXBsZTEOMAwGA1UEAxMFQWxpY2UxIDAeBgkqhkiG9w0B +CQEWEWFsaWNlQGV4YW1wbGUuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE+M2f +By/sRA6V1pKFqecRTE8+LuAHtZxes1wmJZrBBg+bz7uYZfYQxI3dVB0YCSD6Mt3y +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 +G8zcCRiBnmd92UvsRqNQME4wHQYDVR0OBBYEFPI12zQE2qVV8r1pA5mwYuziFQjB +MB8GA1UdIwQYMBaAFPI12zQE2qVV8r1pA5mwYuziFQjBMAwGA1UdEwQFMAMBAf8w +CgYIKoZIzj0EAwMDaAAwZQIwWlGNjb9NyqJSzUSdsEqDSvMZb8yFkxYCIbAVqQ9U +qScUUb9tpJKGsPWwbZsnLVvmAjEAt/ypozbUhQw4dSPpWzrn5BQ0kKbDM3DQJcBA +BEUBoIOol1/jYQPmxajQuxcheFlkMIICgzCCAgqgAwIBAgIJAKWzVCgbsG49MAoG +CCqGSM49BAMDMD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwH +SGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0EwHhcNMTkwNjEyMTQzMTA0WhcNMjAw +NjExMTQzMTA0WjB8MQswCQYDVQQGEwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcT +B0hlcm5kb24xGzAZBgNVBAoTElZpZ2lsIFNlY3VyaXR5IExMQzEXMBUGA1UECxMO +S2V5IE1hbmFnZW1lbnQxGDAWBgNVBAMTD2t0YS5leGFtcGxlLmNvbTB2MBAGByqG +SM49AgEGBSuBBAAiA2IABJf2XsTdVLcYASKJGtWjOAIFB8sXrsiE7G1tC+IP+iOE +dJCZ+UvJ9Enx7v6dtaU4uy1FzuWCar45BVpKVK2TNWT8E7XATkGBTIXGN76yJ5S0 +9FdWp+hVkIkmyCJJujXzV6OBlDCBkTALBgNVHQ8EBAMCB4AwQgYJYIZIAYb4QgEN +BDUWM1RoaXMgY2VydGlmaWNhdGUgY2Fubm90IGJlIHRydXN0ZWQgZm9yIGFueSBw +dXJwb3NlLjAdBgNVHQ4EFgQUbZtc/QOvtbnVi/FknxpW4LWtTQ8wHwYDVR0jBBgw +FoAU8jXbNATapVXyvWkDmbBi7OIVCMEwCgYIKoZIzj0EAwMDZwAwZAIwBniWpO11 +toMsV8fLBpBjA5YGQvd3TAcSw1lNbWpArL+hje1dzQ7pxslnkklv3CTxAjBuVebz +4mN0Qkew2NK/itwlmi7i+QxPs/MSZ7YFsyTA5Z4h2GbLW+zN3xNCC91vfpc= +""" + + def setUp(self): + self.asn1Spec = rfc2985.AttributeSet() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.attr_set_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + for attr in asn1Object: + self.assertIn(attr['type'], rfc5652.cmsAttributesMap) + + av, rest = der_decoder( + attr['values'][0], + asn1Spec=rfc5652.cmsAttributesMap[attr['type']]) + + self.assertFalse(rest) + self.assertTrue(av.prettyPrint()) + self.assertEqual(attr['values'][0], der_encoder(av)) + + if attr['type'] == rfc7906.id_aa_KP_contentDecryptKeyID: + self.assertEqual(univ.OctetString(hexValue='7906'), av) + + def testOpenTypes(self): + openTypesMap = rfc5280.certificateAttributesMap.copy() + openTypesMap.update(rfc5652.cmsAttributesMap) + + substrate = pem.readBase64fromText(self.attr_set_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, openTypes=openTypesMap, + decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + for attr in asn1Object: + if attr['type'] == rfc7906.id_aa_KP_contentDecryptKeyID: + self.assertEqual( + univ.OctetString(hexValue='7906'), attr['values'][0]) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc7914.py b/tests/test_rfc7914.py new file mode 100644 index 0000000..e0b1cb3 --- /dev/null +++ b/tests/test_rfc7914.py @@ -0,0 +1,97 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5958 +from pyasn1_modules import rfc7914 +from pyasn1_modules import rfc8018 + + +# From RFC 7914, Section 13 + +class MultiprimeRSAPrivateKeyTestCase(unittest.TestCase): + pem_text = """\ +MIHiME0GCSqGSIb3DQEFDTBAMB8GCSsGAQQB2kcECzASBAVNb3VzZQIDEAAAAgEI +AgEBMB0GCWCGSAFlAwQBKgQQyYmguHMsOwzGMPoyObk/JgSBkJb47EWd5iAqJlyy ++ni5ftd6gZgOPaLQClL7mEZc2KQay0VhjZm/7MbBUNbqOAXNM6OGebXxVp6sHUAL +iBGY/Dls7B1TsWeGObE0sS1MXEpuREuloZjcsNVcNXWPlLdZtkSH6uwWzR0PyG/Z ++ZXfNodZtd/voKlvLOw5B3opGIFaLkbtLZQwMiGtl42AS89lZg== +""" + + def setUp(self): + self.asn1Spec = rfc5958.EncryptedPrivateKeyInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + ea = asn1Object['encryptionAlgorithm'] + + self.assertEqual(rfc8018.id_PBES2, ea['algorithm']) + self.assertIn(ea['algorithm'], rfc5280.algorithmIdentifierMap) + + params, rest = der_decoder( + ea['parameters'], + asn1Spec=rfc5280.algorithmIdentifierMap[ea['algorithm']]) + + self.assertFalse(rest) + self.assertTrue(params.prettyPrint()) + self.assertEqual(ea['parameters'], der_encoder(params)) + + kdf = params['keyDerivationFunc'] + + self.assertEqual(rfc7914.id_scrypt, kdf['algorithm']) + self.assertIn(kdf['algorithm'], rfc5280.algorithmIdentifierMap) + + kdfp, rest = der_decoder( + kdf['parameters'], + asn1Spec=rfc5280.algorithmIdentifierMap[kdf['algorithm']]) + + self.assertFalse(rest) + self.assertTrue(kdfp.prettyPrint()) + self.assertTrue(kdf['parameters'], der_encoder(kdfp)) + self.assertEqual(1048576, kdfp['costParameter']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + ea = asn1Object['encryptionAlgorithm'] + + self.assertEqual(rfc8018.id_PBES2, ea['algorithm']) + + params = asn1Object['encryptionAlgorithm']['parameters'] + + self.assertEqual( + rfc7914.id_scrypt, params['keyDerivationFunc']['algorithm']) + + kdfp = params['keyDerivationFunc']['parameters'] + + self.assertEqual(1048576, kdfp['costParameter']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc8017.py b/tests/test_rfc8017.py new file mode 100644 index 0000000..9601997 --- /dev/null +++ b/tests/test_rfc8017.py @@ -0,0 +1,125 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc8017 +from pyasn1_modules import rfc2985 + + +class SMIMECapabilitiesTestCase(unittest.TestCase): + smime_capabilities_pem_text = """\ +MIIBAzA8BgkqhkiG9w0BAQcwL6APMA0GCWCGSAFlAwQCAgUAoRwwGgYJKoZIhvcN +AQEIMA0GCWCGSAFlAwQCAgUAMDwGCSqGSIb3DQEBCjAvoA8wDQYJYIZIAWUDBAIC +BQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQAwDQYJKoZIhvcNAQECBQAw +DQYJKoZIhvcNAQEEBQAwDQYJKoZIhvcNAQEFBQAwDQYJKoZIhvcNAQEOBQAwDQYJ +KoZIhvcNAQELBQAwDQYJKoZIhvcNAQEMBQAwDQYJKoZIhvcNAQENBQAwDQYJKoZI +hvcNAQEPBQAwDQYJKoZIhvcNAQEQBQA= +""" + + def setUp(self): + self.asn1Spec = rfc2985.SMIMECapabilities() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.smime_capabilities_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + for cap in asn1Object: + self.assertIn(cap['algorithm'], rfc5280.algorithmIdentifierMap) + + if cap['parameters'].hasValue(): + p, rest = der_decoder( + cap['parameters'], + asn1Spec=rfc5280.algorithmIdentifierMap[cap['algorithm']]) + + self.assertFalse(rest) + if not p == univ.Null(""): + self.assertTrue(p.prettyPrint()) + self.assertEqual(cap['parameters'], der_encoder(p)) + + if cap['algorithm'] == rfc8017.id_RSAES_OAEP: + self.assertEqual( + rfc8017.id_sha384, p['hashFunc']['algorithm']) + self.assertEqual( + rfc8017.id_mgf1, p['maskGenFunc']['algorithm']) + + def OpenTypesCodec(self): + substrate = pem.readBase64fromText(self.smime_capabilities_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + for cap in asn1Object: + if cap['algorithm'] == rfc8017.id_RSAES_OAEP: + p = cap['parameters'] + self.assertEqual( + rfc8017.id_sha384, p['hashFunc']['algorithm']) + self.assertEqual( + rfc8017.id_mgf1, p['maskGenFunc']['algorithm']) + + +class MultiprimeRSAPrivateKeyTestCase(unittest.TestCase): + pem_text = """\ +MIIE2QIBAQKCAQEAn82EqwXasE2TFNSmZucB8LNza2mOWLHF3nxpxKXalPMDvezc +5Dq7Ytcv/k9jJL4j4jYfvR4yyZdU9iHLaD6hOINZ8E6hVpx/4c96ZUSOLzD2g+u+ +jIuoNfG+zygSBGYCS6BLCAIsZ+2wUyxYpLJknHJld9/jy+aLmmyrilhH9dH5AUiV +3NeWht/68++dMXf4ZI/gV4bMSlWhggxkz2WJJpiQdCdJatGkwNDkHmLA9X0tC6OH +SPE7qYdxG38cYS5F445SgnhDpiK7BodSqYLwgehaDjoOYdEgHVnOcpBCDI5zCJSL +b1c/z8uhrB1xxlECR44wCLcKsIIYQxaEErRJ/wIDAQABAoIBAD+Ra5L0szeqxDVn +GgKZJkZvvBwgU0WpAgMtDo3xQ/A4c2ab0IrhaiU5YJgTUGcPVArqaNm8J4vVrTBz +5QxEzbFDXwWe4cMoYh6bgB7ElKLlIUr8/kGZUfgc7kI29luEjcAIEAC2/RQHesVn +DHkL5OzqZL+4fIwckAMh0tXdflsPgZ/jgIaKca4OqKu4KGnczm3UvqtlvwisAjkx +zMyfZXOLn0vEwP2bfbhQrCVrP7n6a+CV+Kqm8NBWnbiS6x2rWemVVssNTbfXQztq +wC6ZJZCLK7plciDBWvHcS6vxdcsS9DUxuqSV6o/stCGTl1D+9tDx8Od0Eunna2B2 +wAoRHZECVgbNO1bqwfYpp5aFuySWoP+KZz8f/5ZkHjLwiNGpQcqVd4+7Ql2R4qgF +NgSoQQOZFhKtiOeLVU0HYfp6doI4waSINZdF/fJDHD6fY3AMOc/IIMDHHIzbAlYG +vKOocLXWj/2+gcyQ1XoAmrE70aIFUBLSvd7RCi8GI74zYWp5lCSvO850Z4GsWSZT +41iF13sTDDJPm3+BbzMvEu2GuACi/8/IpbUr24/FP9Cp1Rf7kwJWAgMxfoshbrNu +ebQB5laHNnT+DYhrOFVRNiNDaD2bUNSetrFidosWtD4ueHxMGENwa4BbFJ9+UrdP +fyxC6k7exM7khGjaNZczwTep1VpYtKjzP/bp9KcCVgYoj9s9HZ1FCAsNEPodjGfd +AcPTQS9mIa7wzy19B7uvFQJXPURi/p4KKBMVQ99Pp8/r9lJzxxiEf8FyPr8N7lZM +EUKkFkDrZQDhKpsrHWSNj6yRFlltAlYC7dYR8KLEWoOUATLosxQhwgypv+23r+d4 +ZdPOdDv9n8Kmj+NFy/oISFfdXzlOU4RWQtMx3hEwAabwct7vjiJEej/kmiTqco02 +17tt13VvvQ5ZXF73dDCCAQwwggEIAlYDfMpM1WNfxcLLOgkRZ+0S9OvIrEOi0ALV +SquTdi/thhCuCsK3lMD4miN9te8j16YtqEFVWXC3a6DWwIJ6m/xZ50bBwPqM8RsI +6FWhZw4Dr5VqjYXUvwJWAvapRk9SydDYri/cAtGIkUJVlspkE1emALAaSw30vmfd +hrgYLT6YGOmK3UmcNJ4NVeET275MXWF1ZOhkOGKTN6aj5wPhJaHBMnmUQrq7GwC6 +/LfUkSsCVgMCDTV9gbFW8u6TcTVW85dBIeUGxZh1T2pbU3dkGO3IOxOhzJUplH4/ +EeEs9dusHakg1ERXAg4Vo1YowPW8kuVbZ9faxeVrmuER5NcCuZzS5X/obGUw +""" + + def setUp(self): + self.asn1Spec = rfc8017.RSAPrivateKey() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc8018.py b/tests/test_rfc8018.py new file mode 100644 index 0000000..f354c63 --- /dev/null +++ b/tests/test_rfc8018.py @@ -0,0 +1,58 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc8018 + + +class PWRITestCase(unittest.TestCase): + rfc3211_ex1_pem_text = """\ +o1MCAQCgGgYJKoZIhvcNAQUMMA0ECBI0Vnh4VjQSAgEFMCAGCyqGSIb3DQEJEAMJMBEGBSsO +AwIHBAjv5ZjvIbM9bQQQuBslZe43PKbe3KJqF4sMEA== +""" + + def setUp(self): + self.asn1Spec = rfc5652.RecipientInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.rfc3211_ex1_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + alg_oid = asn1Object['pwri']['keyDerivationAlgorithm']['algorithm'] + + self.assertEqual(rfc8018.id_PBKDF2, alg_oid) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.rfc3211_ex1_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + icount = (asn1Object['pwri']['keyDerivationAlgorithm'] + ['parameters']['iterationCount']) + + self.assertEqual(5, icount) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc8103.py b/tests/test_rfc8103.py new file mode 100644 index 0000000..002f5c9 --- /dev/null +++ b/tests/test_rfc8103.py @@ -0,0 +1,53 @@ +# +# 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 +import unittest + +from pyasn1.codec.der import decoder as der_decoder +from pyasn1.codec.der import encoder as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc8103 + + +class CAEADChaCha20Poly1305TestCase(unittest.TestCase): + alg_id_pem_text = "MBsGCyqGSIb3DQEJEAMSBAzK/rq++s7brd7K+Ig=" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.alg_id_pem_text) + asn1Object, rest = der_decoder.decode( + substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(rfc8103.id_alg_AEADChaCha20Poly1305, asn1Object[0]) + + param, rest = der_decoder.decode( + asn1Object[1], rfc8103.AEADChaCha20Poly1305Nonce()) + + self.assertFalse(rest) + self.assertTrue(param.prettyPrint()) + self.assertEqual( + rfc8103.AEADChaCha20Poly1305Nonce(value='\xca\xfe\xba\xbe\xfa' + '\xce\xdb\xad\xde\xca' + '\xf8\x88'), + param) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) + + diff --git a/tests/test_rfc8209.py b/tests/test_rfc8209.py new file mode 100644 index 0000000..1afd77f --- /dev/null +++ b/tests/test_rfc8209.py @@ -0,0 +1,63 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc8209 + + +class CertificateTestCase(unittest.TestCase): + cert_pem_text = """\ +MIIBiDCCAS+gAwIBAgIEAk3WfDAKBggqhkjOPQQDAjAaMRgwFgYDVQQDDA9ST1VU +RVItMDAwMEZCRjAwHhcNMTcwMTAxMDUwMDAwWhcNMTgwNzAxMDUwMDAwWjAaMRgw +FgYDVQQDDA9ST1VURVItMDAwMEZCRjAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC +AARzkbq7kqDLO+EOWbGev/shTgSpHgy6GxOafTjZD3flWqBbjmlWeOD6FpBLVdnU +9cDfxYiV7lC8T3XSBaJb02/1o2MwYTALBgNVHQ8EBAMCB4AwHQYDVR0OBBYEFKtN +kQ9VyucaIV7zyv46zEW17sFUMBMGA1UdJQQMMAoGCCsGAQUFBwMeMB4GCCsGAQUF +BwEIAQH/BA8wDaAHMAUCAwD78KECBQAwCgYIKoZIzj0EAwIDRwAwRAIgB7e0al+k +8cxoNjkDpIPsfIAC0vYInUay7Cp75pKzb7ECIACRBUqh9bAYnSck6LQi/dEc8D2x +OCRdZCk1KI3uDDgp +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + extn_list = [] + + for extn in asn1Object['tbsCertificate']['extensions']: + extn_list.append(extn['extnID']) + if extn['extnID'] in rfc5280.certificateExtensionsMap.keys(): + extnValue, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + if extn['extnID'] == rfc5280.id_ce_extKeyUsage: + self.assertIn(rfc8209.id_kp_bgpsec_router, extnValue) + + self.assertIn(rfc5280.id_ce_extKeyUsage, extn_list) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc8226.py b/tests/test_rfc8226.py new file mode 100644 index 0000000..aa5257c --- /dev/null +++ b/tests/test_rfc8226.py @@ -0,0 +1,104 @@ +# +# 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 +import unittest + +from pyasn1.codec.der import decoder as der_decoder +from pyasn1.codec.der import encoder as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc8226 + + +class JWTClaimConstraintsTestCase(unittest.TestCase): + jwtcc_pem_text = ("MD2gBzAFFgNmb2+hMjAwMBkWA2ZvbzASDARmb28xDARmb28yDARmb2" + "8zMBMWA2JhcjAMDARiYXIxDARiYXIy") + + def setUp(self): + self.asn1Spec = rfc8226.JWTClaimConstraints() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.jwtcc_pem_text) + asn1Object, rest = der_decoder.decode( + substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + +class TNAuthorizationListTestCase(unittest.TestCase): + tnal_pem_text = ("MCugBxYFYm9ndXOhEjAQFgo1NzE1NTUxMjEyAgIDFKIMFgo3MDM1NTU" + "xMjEy") + + def setUp(self): + self.asn1Spec = rfc8226.TNAuthorizationList() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.tnal_pem_text) + asn1Object, rest = der_decoder.decode( + substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + +class CertificateOpenTypesTestCase(unittest.TestCase): + cert_pem_text = """\ +MIICkTCCAhegAwIBAgIJAKWzVCgbsG4+MAoGCCqGSM49BAMDMD8xCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9n +dXMgQ0EwHhcNMTkwNzE4MTUwNzQ5WhcNMjAwNzE3MTUwNzQ5WjBxMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xKDAmBgNVBAoTH0Zh +a2UgVGVsZXBob25lIFNlcnZpY2UgUHJvdmlkZXIxGTAXBgNVBAMTEGZha2UuZXhh +bXBsZS5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARLyLhnsvrS9WBY29tmN2LI +CF/wuX4ohhUy3sxO0ynCplHHojpDg+tghGzusf0aLtMDu1II915O8YK5XVL+KZJD +C82jybxWIKjjzX2qc5/O06joUttdEDzkTaD0kgbcXl6jgawwgakwCwYDVR0PBAQD +AgeAMEIGCWCGSAGG+EIBDQQ1FjNUaGlzIGNlcnRpZmljYXRlIGNhbm5vdCBiZSB0 +cnVzdGVkIGZvciBhbnkgcHVycG9zZS4wHQYDVR0OBBYEFHOI3GpDt9dWsTAZxhcj +96uyL2aIMB8GA1UdIwQYMBaAFPI12zQE2qVV8r1pA5mwYuziFQjBMBYGCCsGAQUF +BwEaBAowCKAGFgRmYWtlMAoGCCqGSM49BAMDA2gAMGUCMQCy+qFhT7X1i18jcyIa +Jkgz/tumrPsaBA2RihkooTEr4GbqC650Z4Cwt7+x2xZq37sCMFSM6fRueLyV5StG +yEFWA6G95b/HbtPMTjLpPKtrOjhofc4LyVCDYhFhKzpvHh1qeA== +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decoder.decode( + substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + extn_list = [] + for extn in asn1Object['tbsCertificate']['extensions']: + extn_list.append(extn['extnID']) + if extn['extnID'] in rfc5280.certificateExtensionsMap.keys(): + extnValue, rest = der_decoder.decode( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertEqual( + extn['extnValue'], der_encoder.encode(extnValue)) + + if extn['extnID'] == rfc8226.id_pe_TNAuthList: + self.assertEqual('fake', extnValue[0]['spc']) + + self.assertIn(rfc8226.id_pe_TNAuthList, extn_list) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc8358.py b/tests/test_rfc8358.py new file mode 100644 index 0000000..48a01ce --- /dev/null +++ b/tests/test_rfc8358.py @@ -0,0 +1,195 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc8358 + + +class P7STestCase(unittest.TestCase): + pem_text_list = ( +"""\ +MIIJWgYJKoZIhvcNAQcCoIIJSzCCCUcCAQMxDTALBglghkgBZQMEAgEwDQYLKoZIhvcNAQkQ +ARugggZ0MIIGcDCCBVigAwIBAgIRANa58hQvZ26svTWQaGtqo/YwDQYJKoZIhvcNAQELBQAw +gZcxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcT +B1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMT0wOwYDVQQDEzRDT01PRE8g +UlNBIENsaWVudCBBdXRoZW50aWNhdGlvbiBhbmQgU2VjdXJlIEVtYWlsIENBMB4XDTE1MDIx +MjAwMDAwMFoXDTIwMDIxMjIzNTk1OVowgZUxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhWaXJn +aW5pYTEPMA0GA1UEBxMGUmVzdG9uMRMwEQYDVQQKEwpJRVRGIFRydXN0MRkwFwYDVQQLExBT +ZWNyZXRhcmlhdCBXZXN0MQ0wCwYDVQQDEwRJRVRGMSMwIQYJKoZIhvcNAQkBFhRpZXRmLWFj +dGlvbkBpZXRmLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMUkKtMPP1RA +FU6sxMezYJKCt4rw30RDieB8/P67TMhA6j8Um4a2Xo+CP9Ce1oMri2bwaaQPYWB4ciEL32za +0NUE0B0iCjZZl36hon6wW6mJw1NGD/AFxnKWzhkSWG6BHMoeOAzu/ye8sHu4Jp5nazpGptK7 +30SjTS3JJFU9pHwQY6JlcmwVv0j2rsT3gj92Cbj5S+U5wCSE6+mZbCC+VPFeeI1kFITwyaIm +uK9kSYHr15OXua/jrYNrHNRfqtexGKSgnUT96KkTh9TVvkMETB1WJS4WuEIP6GITvwVTp0lA +qS3oNO4SM4tgFVdYqppcvZBg52kHY9y7IdR156c99zzZDBfWBduqjs/AXa0uol0EJd7qFLUs +xEJ96XN3tPgR/Cwq18ec29pZQH6kO81Kato/RsQrj6A05TFx/J0MYE0R1MZqvIDUu55vlicb +wT2lpXMiz1szKuvjTZRR9H/IgbKPNpt/kDUSgXLYwuKBm+nBoJXgybEyJ+A4arb60d9Uiusu +UA8/h6s1rDMuTnIYMbIii4Y+KgevBWPawqk0xioilEMJ0RBaBVrDreuFlK8aYh+Jo2piruBA +QnB9ZaPmEM1HPNArJxqL6XcUJTkFxNSksOATDFV5sEoBWYIe6qv2nV2r/HWDAEaa4WH2h3o/ +kASarXk3SxPXmfjOOr1XgpKjAgMBAAGjggG1MIIBsTAfBgNVHSMEGDAWgBSCr2yM+MX+lmF8 +6B89K3FIXsSLwDAdBgNVHQ4EFgQU7Olc92Oy6nkCvpv6jCj6qN8YPtUwDgYDVR0PAQH/BAQD +AgeAMAwGA1UdEwEB/wQCMAAwRgYDVR0gBD8wPTA7BgwrBgEEAbIxAQIBAwUwKzApBggrBgEF +BQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNvbS9DUFMwWgYDVR0fBFMwUTBPoE2gS4ZJ +aHR0cDovL2NybC5jb21vZG9jYS5jb20vQ09NT0RPUlNBQ2xpZW50QXV0aGVudGljYXRpb25h +bmRTZWN1cmVFbWFpbENBLmNybDCBiwYIKwYBBQUHAQEEfzB9MFUGCCsGAQUFBzAChklodHRw +Oi8vY3J0LmNvbW9kb2NhLmNvbS9DT01PRE9SU0FDbGllbnRBdXRoZW50aWNhdGlvbmFuZFNl +Y3VyZUVtYWlsQ0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20w +HwYDVR0RBBgwFoEUaWV0Zi1hY3Rpb25AaWV0Zi5vcmcwDQYJKoZIhvcNAQELBQADggEBAGPm +QUKHxkEQ9vk69vIP68anHc8UsTv5powtLSXLqUw3rAoKAdoWkKjb7ZByHCuFiNk1BvTnhQPh +LAZm5dI8dYWKp3zgWVxsCXOQv2K4XbaQpIk8KKdLycHWsOq2OD4xBdhfTQqDj9EidhxaLf4B +bRUePOuWVvwNqHI6OQ9FbRllUsTsSH3XK7z9Ru/0Ub07uEzmWyrIpeFRLJUg9EqQj25pw8j7 +N9ym8ItpfEQvK4Nrzt9KnGwFDaNOUjYAvejig9iUNdOXEQKVzbq8fC25HrXPQisq8u2jrP38 +cRqzwgGHZ1bJrQa8+LPBfADZ4ZHeqlEe6IqZhS/wDSuDNCIZHtkxggKqMIICpgIBA4AU7Olc +92Oy6nkCvpv6jCj6qN8YPtUwCwYJYIZIAWUDBAIBoGswGgYJKoZIhvcNAQkDMQ0GCyqGSIb3 +DQEJEAEbMBwGCSqGSIb3DQEJBTEPFw0xOTA2MDkxNjU3NTdaMC8GCSqGSIb3DQEJBDEiBCDx +ACvH9u26K1BdX+IPp6vguUAtA9k0lp9JMNunvXTuQzANBgkqhkiG9w0BAQEFAASCAgBY8kFl +SxQIvU4n6LaVoAV6ibHrlCqOp9KrUc9DmwXtDifsgoGfhDHb6i5k9BSHmerjTGF6mLlquPUV +Z2EHSUuVpk8rX//ki6vngq91+f+ufrzEpvO6BLc2aO/zOat0W3U2hiq3zJSLMYMNZhX484Nq +9+ImsU0S5f32ZpEXH0lFINUaZFo0eRAOZywqNuY57stjWBxTI6MA00S0+eMuWlmkMy0C2LL9 +BQvWW01/ri2UDEprAiKo2sXLcScgHimEVYHuWsrnP+sJ3XVWRsWGRW2i5qIalu2ZGmmIU/vg +bdBzQnAjCoS2xC5Kwv+cqtUiiyLI0nnuu1aKKi4hivmt1n+hSIWWgGNwTFn3S4+mYDDNSH0u +ocOr0uDFVv/SH9QPQuGh9rpSz3cd3hlA4R63Rylm46Tt6DnXiovu0mDoos68UQjIAPXWj1ES +Peeubp+wSbuqN8Rh+koZU+HK7YpsR2bB4hL0GIwMA9lQjGSCxPCt1ViRL6zAWECzQC1YgLyc ++f1Fe8pkaWUbZz+18H/rJoKsXiNWH8yhfAyk+JGTxc4qxWJ/BuF0vzSyuVEffuxIHrOMZTpO ++xfAaJVDqFjxT5yKj3dCfy6XSDZq39AeX/w26/WfH+0ALRiViAAaMHSldbawVR/W3isecDWF +tlU4NSJMLi/tTohe0QN1fjOaFryAvw== +""", +"""\ +MIIJWgYJKoZIhvcNAQcCoIIJSzCCCUcCAQMxDTALBglghkgBZQMEAgEwDQYLKoZIhvcNAQkQ +ARygggZ0MIIGcDCCBVigAwIBAgIRANa58hQvZ26svTWQaGtqo/YwDQYJKoZIhvcNAQELBQAw +gZcxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcT +B1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMT0wOwYDVQQDEzRDT01PRE8g +UlNBIENsaWVudCBBdXRoZW50aWNhdGlvbiBhbmQgU2VjdXJlIEVtYWlsIENBMB4XDTE1MDIx +MjAwMDAwMFoXDTIwMDIxMjIzNTk1OVowgZUxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhWaXJn +aW5pYTEPMA0GA1UEBxMGUmVzdG9uMRMwEQYDVQQKEwpJRVRGIFRydXN0MRkwFwYDVQQLExBT +ZWNyZXRhcmlhdCBXZXN0MQ0wCwYDVQQDEwRJRVRGMSMwIQYJKoZIhvcNAQkBFhRpZXRmLWFj +dGlvbkBpZXRmLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMUkKtMPP1RA +FU6sxMezYJKCt4rw30RDieB8/P67TMhA6j8Um4a2Xo+CP9Ce1oMri2bwaaQPYWB4ciEL32za +0NUE0B0iCjZZl36hon6wW6mJw1NGD/AFxnKWzhkSWG6BHMoeOAzu/ye8sHu4Jp5nazpGptK7 +30SjTS3JJFU9pHwQY6JlcmwVv0j2rsT3gj92Cbj5S+U5wCSE6+mZbCC+VPFeeI1kFITwyaIm +uK9kSYHr15OXua/jrYNrHNRfqtexGKSgnUT96KkTh9TVvkMETB1WJS4WuEIP6GITvwVTp0lA +qS3oNO4SM4tgFVdYqppcvZBg52kHY9y7IdR156c99zzZDBfWBduqjs/AXa0uol0EJd7qFLUs +xEJ96XN3tPgR/Cwq18ec29pZQH6kO81Kato/RsQrj6A05TFx/J0MYE0R1MZqvIDUu55vlicb +wT2lpXMiz1szKuvjTZRR9H/IgbKPNpt/kDUSgXLYwuKBm+nBoJXgybEyJ+A4arb60d9Uiusu +UA8/h6s1rDMuTnIYMbIii4Y+KgevBWPawqk0xioilEMJ0RBaBVrDreuFlK8aYh+Jo2piruBA +QnB9ZaPmEM1HPNArJxqL6XcUJTkFxNSksOATDFV5sEoBWYIe6qv2nV2r/HWDAEaa4WH2h3o/ +kASarXk3SxPXmfjOOr1XgpKjAgMBAAGjggG1MIIBsTAfBgNVHSMEGDAWgBSCr2yM+MX+lmF8 +6B89K3FIXsSLwDAdBgNVHQ4EFgQU7Olc92Oy6nkCvpv6jCj6qN8YPtUwDgYDVR0PAQH/BAQD +AgeAMAwGA1UdEwEB/wQCMAAwRgYDVR0gBD8wPTA7BgwrBgEEAbIxAQIBAwUwKzApBggrBgEF +BQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNvbS9DUFMwWgYDVR0fBFMwUTBPoE2gS4ZJ +aHR0cDovL2NybC5jb21vZG9jYS5jb20vQ09NT0RPUlNBQ2xpZW50QXV0aGVudGljYXRpb25h +bmRTZWN1cmVFbWFpbENBLmNybDCBiwYIKwYBBQUHAQEEfzB9MFUGCCsGAQUFBzAChklodHRw +Oi8vY3J0LmNvbW9kb2NhLmNvbS9DT01PRE9SU0FDbGllbnRBdXRoZW50aWNhdGlvbmFuZFNl +Y3VyZUVtYWlsQ0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20w +HwYDVR0RBBgwFoEUaWV0Zi1hY3Rpb25AaWV0Zi5vcmcwDQYJKoZIhvcNAQELBQADggEBAGPm +QUKHxkEQ9vk69vIP68anHc8UsTv5powtLSXLqUw3rAoKAdoWkKjb7ZByHCuFiNk1BvTnhQPh +LAZm5dI8dYWKp3zgWVxsCXOQv2K4XbaQpIk8KKdLycHWsOq2OD4xBdhfTQqDj9EidhxaLf4B +bRUePOuWVvwNqHI6OQ9FbRllUsTsSH3XK7z9Ru/0Ub07uEzmWyrIpeFRLJUg9EqQj25pw8j7 +N9ym8ItpfEQvK4Nrzt9KnGwFDaNOUjYAvejig9iUNdOXEQKVzbq8fC25HrXPQisq8u2jrP38 +cRqzwgGHZ1bJrQa8+LPBfADZ4ZHeqlEe6IqZhS/wDSuDNCIZHtkxggKqMIICpgIBA4AU7Olc +92Oy6nkCvpv6jCj6qN8YPtUwCwYJYIZIAWUDBAIBoGswGgYJKoZIhvcNAQkDMQ0GCyqGSIb3 +DQEJEAEcMBwGCSqGSIb3DQEJBTEPFw0xOTA2MDkxNjU3NTdaMC8GCSqGSIb3DQEJBDEiBCBg +ifxBsUb2E8RicFvqZB+NJEs1FOG4hFFU1bPqV2UwGzANBgkqhkiG9w0BAQEFAASCAgCApFAS +4+cYrnkMebrANXw7/TGn6Qx01p9fuOugQb6lcfE5CysIKGLJJogs0BXwHK4jTeJRdt/lutuz +bACg1bakABxuCiLWMu3pKCKS94qAgElYgWru+pAxPhuslz5MwAU0qFW3KnaNq3f5wXlVQ+h2 +l9spSiLhAQ+vLTLfotn6tCmUfjaaYsoNIUGg6b/2vH75QGYaXDq9YGoCrrkDbaRS4eDenSL5 +S2fBTZ5VMJE/1VQY1D5CWqt2CTfzRkNkU7mkarPy6SPvguDlqKJJnFaZJmeIYbGOpDt6KxWc +DLFD9+J6CH492QwlHxDtM94nK1oIaqdu9TTV94t0ToGezElOZZuVA2DVkov5DzrYQLI5GjMw +7iHXW1ewCaGF38DdOopqBYp7jcCCZpruKBWDq/uz40MzSBrffYTP/dg4//8Awvt/JomvTUoH +E18Pt/G2cqdw0NqOE7YEcFpsLGfikTWmGhnrcYUkt8odDDAv/vqZRt8DLkB56waQeQw0TLit +2M3gbTSHJ1KFsBM/kqHanVapGtnClkY7hYh8DVpgJymJpupkNFs8lDNbN4C42DhQ6Oz9P2qu +8a/ybEb5gMZ3fsVLvvp6LhbJfqIvYgZO2uKXeKg3eLASD5nVY/Tuhnn2plhx+weKULGys0Ov +zPKZ+N96KLerIBr3FmGByqhr3jNrBw== +""", +"""\ +MIIJWgYJKoZIhvcNAQcCoIIJSzCCCUcCAQMxDTALBglghkgBZQMEAgEwDQYLKoZIhvcNAQkQ +AR2gggZ0MIIGcDCCBVigAwIBAgIRANa58hQvZ26svTWQaGtqo/YwDQYJKoZIhvcNAQELBQAw +gZcxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcT +B1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMT0wOwYDVQQDEzRDT01PRE8g +UlNBIENsaWVudCBBdXRoZW50aWNhdGlvbiBhbmQgU2VjdXJlIEVtYWlsIENBMB4XDTE1MDIx +MjAwMDAwMFoXDTIwMDIxMjIzNTk1OVowgZUxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhWaXJn +aW5pYTEPMA0GA1UEBxMGUmVzdG9uMRMwEQYDVQQKEwpJRVRGIFRydXN0MRkwFwYDVQQLExBT +ZWNyZXRhcmlhdCBXZXN0MQ0wCwYDVQQDEwRJRVRGMSMwIQYJKoZIhvcNAQkBFhRpZXRmLWFj +dGlvbkBpZXRmLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMUkKtMPP1RA +FU6sxMezYJKCt4rw30RDieB8/P67TMhA6j8Um4a2Xo+CP9Ce1oMri2bwaaQPYWB4ciEL32za +0NUE0B0iCjZZl36hon6wW6mJw1NGD/AFxnKWzhkSWG6BHMoeOAzu/ye8sHu4Jp5nazpGptK7 +30SjTS3JJFU9pHwQY6JlcmwVv0j2rsT3gj92Cbj5S+U5wCSE6+mZbCC+VPFeeI1kFITwyaIm +uK9kSYHr15OXua/jrYNrHNRfqtexGKSgnUT96KkTh9TVvkMETB1WJS4WuEIP6GITvwVTp0lA +qS3oNO4SM4tgFVdYqppcvZBg52kHY9y7IdR156c99zzZDBfWBduqjs/AXa0uol0EJd7qFLUs +xEJ96XN3tPgR/Cwq18ec29pZQH6kO81Kato/RsQrj6A05TFx/J0MYE0R1MZqvIDUu55vlicb +wT2lpXMiz1szKuvjTZRR9H/IgbKPNpt/kDUSgXLYwuKBm+nBoJXgybEyJ+A4arb60d9Uiusu +UA8/h6s1rDMuTnIYMbIii4Y+KgevBWPawqk0xioilEMJ0RBaBVrDreuFlK8aYh+Jo2piruBA +QnB9ZaPmEM1HPNArJxqL6XcUJTkFxNSksOATDFV5sEoBWYIe6qv2nV2r/HWDAEaa4WH2h3o/ +kASarXk3SxPXmfjOOr1XgpKjAgMBAAGjggG1MIIBsTAfBgNVHSMEGDAWgBSCr2yM+MX+lmF8 +6B89K3FIXsSLwDAdBgNVHQ4EFgQU7Olc92Oy6nkCvpv6jCj6qN8YPtUwDgYDVR0PAQH/BAQD +AgeAMAwGA1UdEwEB/wQCMAAwRgYDVR0gBD8wPTA7BgwrBgEEAbIxAQIBAwUwKzApBggrBgEF +BQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNvbS9DUFMwWgYDVR0fBFMwUTBPoE2gS4ZJ +aHR0cDovL2NybC5jb21vZG9jYS5jb20vQ09NT0RPUlNBQ2xpZW50QXV0aGVudGljYXRpb25h +bmRTZWN1cmVFbWFpbENBLmNybDCBiwYIKwYBBQUHAQEEfzB9MFUGCCsGAQUFBzAChklodHRw +Oi8vY3J0LmNvbW9kb2NhLmNvbS9DT01PRE9SU0FDbGllbnRBdXRoZW50aWNhdGlvbmFuZFNl +Y3VyZUVtYWlsQ0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20w +HwYDVR0RBBgwFoEUaWV0Zi1hY3Rpb25AaWV0Zi5vcmcwDQYJKoZIhvcNAQELBQADggEBAGPm +QUKHxkEQ9vk69vIP68anHc8UsTv5powtLSXLqUw3rAoKAdoWkKjb7ZByHCuFiNk1BvTnhQPh +LAZm5dI8dYWKp3zgWVxsCXOQv2K4XbaQpIk8KKdLycHWsOq2OD4xBdhfTQqDj9EidhxaLf4B +bRUePOuWVvwNqHI6OQ9FbRllUsTsSH3XK7z9Ru/0Ub07uEzmWyrIpeFRLJUg9EqQj25pw8j7 +N9ym8ItpfEQvK4Nrzt9KnGwFDaNOUjYAvejig9iUNdOXEQKVzbq8fC25HrXPQisq8u2jrP38 +cRqzwgGHZ1bJrQa8+LPBfADZ4ZHeqlEe6IqZhS/wDSuDNCIZHtkxggKqMIICpgIBA4AU7Olc +92Oy6nkCvpv6jCj6qN8YPtUwCwYJYIZIAWUDBAIBoGswGgYJKoZIhvcNAQkDMQ0GCyqGSIb3 +DQEJEAEdMBwGCSqGSIb3DQEJBTEPFw0xOTA3MTQwMTMyMTdaMC8GCSqGSIb3DQEJBDEiBCAJ +zK6u0RRfrSQ2ebn+GOxnbovlG3Raul/1zOOGmTaIPzANBgkqhkiG9w0BAQEFAASCAgBlKYNd +euVzPDqEa13k4nQthmyJUUqjWlAVolgohXioYok8Z5BkKmkp8ANLbvkJl0hV1Al1hutTRNeF +a5ZeWyS6nAWyPFKfRSNqwWLMIi1dX+rO7Vhf15Lz944ZYsqO+O2f7rjWUJmi8/uJKD7cFDiW +uKkPMgvqyIMnnC3ya/sC1vU+0Feqr5JcIMs2AHQeNVe8hzN4T9Pthyax7gqbxTkg3Gyt7Mwy +WLZeK84oJmkl9ANeVgzq+P/cmqUaqtfkBFDSxaTag/eoYM3QfHNisr/jHCazqCh88VMgwhvk +cl6NS9hdH+aOWqQ3FE1c7VJNoQRDT7ztyKCrRJFPc4wZL8tsGkKp1lP4WcaStcbUJ65AdWPb +3CZonLY4UOBotAUpG/PObMCmWBEpr8MN0Q+kuEO2oAe9kBoFsv7MtNfyHE4CuOANRqGLRgOL +72hN8Cy0sGWYUy+2chH3i50cT8XkDV5Rz2Z5xW3SfyAuW53j2WKLFsKkZjfkZBopSJM20V4E +8pPnQQ/ByFwYPyS/xJZc24vsRxgogbrf11JU8hKVkfSsq3JXxUxe5w+Sh1XGTmO5tXDKFfyi +S+VljWVifzXaR3pmTEQPhXH4nBa4K/HYytxofDP3EMli+imil2fFBbBedZkb5CIQ/Ly3soHZ +dZlmZDkyeXJLpkNjRAsG6V82raZd9g== +""", +) + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + oids = [ ] + for pem_text in self.pem_text_list: + substrate = pem.readBase64fromText(pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc5652.id_signedData, asn1Object['contentType']) + + sd, rest = der_decoder(asn1Object['content'], asn1Spec=rfc5652.SignedData()) + + self.assertFalse(rest) + self.assertTrue(sd.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(sd)) + + oids.append(sd['encapContentInfo']['eContentType']) + + self.assertIn(rfc8358.id_ct_asciiTextWithCRLF, oids) + self.assertIn(rfc8358.id_ct_pdf, oids) + self.assertIn(rfc8358.id_ct_xml, oids) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc8360.py b/tests/test_rfc8360.py new file mode 100644 index 0000000..56a76cf --- /dev/null +++ b/tests/test_rfc8360.py @@ -0,0 +1,464 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc8360 + + +class CertExtnsTestCase(unittest.TestCase): + extns_pem_text = """\ +MIJM7TCCRkUGCCsGAQUFBwEcBIJGNzCCRjMwgkXJBAIAATCCRcEDAgACMAoDAgAF +AwQFBRwAMAoDBAMFHCgDAgEEMAoDAwINdAMDAg14AwMCDYwwCgMDAw2oAwMDDbAD +AwIN8AMEAhcTMAMEAxcTOAMEAxdTQAMEBBdTcAMEBRdp4DAMAwQDF2poAwQDF2pw +AwQEF2zQAwMAF20DBAMXbwAwDAMEBBdvEAMEBhdvADAMAwQEF29QAwQHF28AMAwD +BAYXb8ADBAMXb/ADBAUX74ADBAMX+egwDAMEARf8QgMEABf8RDAMAwQAF/xHAwQA +F/xIMAwDBAAX/EsDBAAX/EwDBAAX/E8DAwIYhAMEARjrFgMCABkwCwMDARtuAwQC +G24QMAkDAgAfAwMAH84wDAMEAx/PCAMEAx/PMDAKAwQCH888AwIFADAJAwIAJQMD +ACVuMAkDAwQlcAMCASQDBAIr4XADBAIr+6ADAwMtCAMEBS0rQAMEBS044AMEBi1B +QAMDAS1CAwQHLUuAAwMELVADAwUtgAMEAi36GDAKAwIBLgMEBi6VgDAKAwQELpXQ +AwIALgMDATEMAwMBMjwDAwAydzAJAwIAMwMDADNOAwMAM1AwCQMDATNSAwICMAME +BTSQQAMCADUwCgMDAjYkAwMANiYDAgA5AwQCPQ7gMAoDAgE+AwQGPggAMAwDBAU+ +CGADBAU+DEAwDAMEBz4MgAMEBT4YQDAMAwQHPhiAAwQGPj2AMAsDAwE+PgMEBT5E +ADAMAwQGPkRAAwQFPkTAMAoDAwA+RQMDAT5wMAsDAwA+cwMEBT51ADALAwQGPnVA +AwMAPoYwCwMEBz6HgAMDAD6KAwQGPowAMAwDBAc+jIADBAU+rQAwDAMEBj6tQAME +Bj7BAAMEBT7BgDALAwQGPsHAAwMBPugwCwMDAD7rAwQFPvAAAwQFPvBAMAwDBAc+ +8IADBAc+8QAwDAMEBT7xoAMEBz77AAMDAj78MAwDBAE/jSIDBAE/jSQDBAQ/jgAD +BAVAEMADBAVAHAADBAdAKwADBAZAQUADBAZAicADBAJA7+wDBAVA/SADBAZBEoAD +BARBEtADBAVBJ0ADBAZBY4ADBAVCT2ADBARCVEADBAZCdoADBAVCzUADBAVC1GAD +BAJC+MwwDAMEBUMWIAMEAkMWOAMEAEOePgMEBUPRgAMEBERGwAMEBkUGAAMEBEVe +QAMEBEVecAMEBUWsYAMEBkXCQDAJAwIATQMDAk3YMAwDBAVN3CADBAdQQwAwDAME +BFBDkAMEBVBHADAMAwQEUEcwAwQFUEhAMAwDBARQSHADBAVQS4AwDAMEBlBLwAME +BFBWADAMAwQFUFYgAwQGUFcAMAsDBAVQV2ADAwNQUDALAwQEUFgQAwMAUF4wDAME +BFBfEAMEBlDwgDALAwQEUPDQAwMBUPQwCwMEBFD2EAMDA1DwMAwDBARQ+BADBAZQ ++AAwDAMEBFD4UAMEBlD5ADAMAwQEUPlQAwQFUPoAMAsDBARQ+jADAwJRADALAwQG +UQRAAwMBUQgwDAMEB1EKgAMEBVEVQDAMAwQEURVwAwQGURYAMAwDBAVRFmADBARR +F8AwDAMEBVEX4AMEBlEaADAMAwQEURpQAwQFUR1AMAsDBARRHXADAwJRQDALAwMD +UUgDBAVRW8AwCwMEBFFb8AMDBlGAMAsDAwBRwQMEB1JlADALAwQGUmXAAwMHUgAw +DAMEB1KAgAMEB1KBADALAwMBUoIDBAZSlwAwCwMEBVKXYAMDAlKYMAsDAwFSngME +B1LJADALAwMBUsoDBANTjxAwCwMEBVOPIAMDAlQgMAsDAwBUJQMEBVTNQDALAwQH +VM2AAwMAVOgwDAMEB1TpgAMEBVf3gDAMAwQDV/eoAwQFV/9AMAwDBAdX/4ADBARZ +0OAwCwMDAFnRAwQEWe8gMAwDBAZZ70ADBAVb4QAwDAMEAVvhIgMEAlvrADALAwQB +W+sGAwMBXMgwCwMDAlzMAwQFXbNAAwQDXbNoAwQCXbN4MAwDBAdds4ADBABeGhow +DAMEAl4aHAMEAF4aHjAMAwQFXhogAwQCXhooAwQAXhotMAwDBAReGjADBABeGkIw +DAMEAl4aRAMEAF4aSDAMAwQBXhpKAwQCXhpQMAwDBAFeGlYDBAJeZwAwDAMEA15n +CAMEBF6+wAMEBF6+8DAMAwQHXr+AAwQGX6OAMAsDBARfo9ADAwBfqDAMAwQFX6kg +AwQCX7W4MAoDBAZftcADAgVAAwQFYAmAAwQEYH2QAwMAYoADAwNlOAMEAmfhyAME +AmfniAMEAmfxbAMEAmf7pAMEAmf8WAMEA2glIAMEAmiZVAMEAWjoJAMEBmjpQAME +Amjz2AMEAmj0CDAMAwQBa5aiAwQCa5awAwQEa6GgAwQFa7WAAwQAa79EMAkDAgBt +AwMCbegwCwMEBG3sEAMDAm3wMAkDAwBt9QMCAWwwCwMDAHHLAwQGccuAAwMBdMoD +BAJ9PkgDAwCAAAMDAIAHAwMAgBAwCgMDAIAnAwMBgCgDAwCALTAKAwMAgEEDAwSA +QAMDAYBWAwMAgF0DAwCAYgMEB4B0gAMDAIB8AwMAgH8DAwGAgjAKAwMAgIsDAwCA +jgMDAICoAwMAgLADAwGAsgMDAIDHAwMAgMwDAwCA1gMDAIDoAwMAgOoDAwCA8AMD +AIDzAwMAgPYwCgMDAIELAwMBgQwDAwCBEAMDAIEUAwMBgRoDAwCBHwMDAIFDMAoD +AwCBRQMDAIFGAwMAgUkDAwCBWDAKAwMBgWYDAwCBaAMDAIF9AwMAgYEDAwCBhAMD +AYGOAwMAgakDAwCBrzAKAwMAgbEDAwCBsjAKAwMAgbUDAwGBuAMDAIG7AwMBgcID +AwCBxwMDAIHOAwMAgdADAwGB1gMDAIHZMAoDAwCB6QMDAIHqMAoDAwSB8AMDAIHy +AwMAgfcDAwCCAAMDAYIYAwMAghwDAwCCIAMDAIIlAwMAgiswCgMDAII7AwMAgjwD +AwGCQgMDAIJJAwMAgksDAwGCTjAKAwMBglIDAwCCVAMDAYJYAwMBglwDAwCCYgMD +AIJkAwMAgmgDAwCCcAMDAIJzAwMAgngDAwCCfQMDAIKFAwMAgogwCgMDAYKKAwMB +gpQDAwCCnwMDAIKhAwQHgqSAAwMAgrQDAwCCtzAKAwMAgrkDAwCCugMDAIK8AwMA +gr4DAwGCwAMDAILGAwMAgswDAwCCzgMDAYLQAwMAgt8wCgMDAILhAwMAgvQDAwCC +9gMEA4L4MDAMAwQBgvg6AwQGgvgAMAwDBAKC+EQDBAKC+GgDAwCC+wMDAIL/AwMA +gwEDAwCDYQMDAINjAwMAg2YDAwCDbzAKAwMBg3IDAwGDdAMDAIOCAwMAg5gDAwGD +mjAKAwMAg58DAwCDoDAKAwMCg6QDAwCDpgMDAIOpMAoDAwCDrQMDAYOwAwMAg7QD +AwCDvAMDAIPNAwMAg88DAwCD0wMDAIPcAwMAg+AwCgMDAIPjAwMAg+QDAwCD5wMD +AIPqAwMAg+0DAwCD9gMDAIP7AwMAg/4wCgMDBoRAAwMAhE4DAwCEkjAKAwMAhJUD +AwCElgMDAISZAwMAhJswCgMDAISlAwMBhKgDAwCEqwMDAISwAwMAhLQwCgMDAIS5 +AwMChLgwCgMDAITDAwMAhMQDAwCExwMDAITjMAoDAwCE5QMDA4TgAwMAhPQDAwCE +/AMDAoYAAwMAhhEDAwCGEwMDAIYVAwMAhhkwCgMDAIYbAwMAhhwDAwCGHjAKAwMB +hiIDAwGGJAMDAIYvAwMAhjYwCgMDAYY6AwMBhjwDAwCGTAMDAIZRAwMAhlMwCgMD +AYZaAwMAhm4DAwCGdwMDAIaCAwMAhooDAwGGjjAKAwMAhpEDAwKGkAMDAIaXAwMA +hpswCgMDAIadAwMAhp4DAwCGqQMDAIarAwMAhrAwCgMDAIa3AwMAhrgDAwCGvAMD +AIa/AwMAhssDAwCGzjAKAwMChtQDAwCG1jAKAwMAhtsDAwCG3jAKAwMAhuEDAwKG +4AMDAIbvMAoDAwCG9QMDA4bwAwMAhvkDAwCG/wMEAodUNAMEAodUlAMDAIdaAwMA +h8QDBAeIjwAwCwMEBIiQEAMDAIiQAwMAiJQwCgMDAIibAwMBiJwDBAeInoAwCgMD +AIijAwMAiKQwCgMDAIipAwMAiKoDAwGIrAMDAIjHAwMAiMkDAwCIzgMDAIjhAwMB +iOYDAwCI8wMDAIj/AwMAiREwCgMDAIkhAwMAiSIwCgMDAIkrAwMAiSwDAwCJLwMD +AIkyMAoDAwCJNwMDAIk4AwMAiTowCgMDAok8AwMAiT4wCgMDAIlJAwMAiUoDAwCJ +XQMDAIlgAwMAiWUDAwCJaQMDAIlsAwMBiXgDAwCJgQMDAImFAwMAiYoDAwCJnAMD +AImjAwMAia4DAwCJvzAKAwMAicEDAwKJwAMDAYnMAwMAidADAwCJ1TAKAwMAidkD +AwCJ2jAKAwMAid0DAwCJ4AMDAIniAwMAifgDAwGJ+gMDAIn9MAoDAwCKAwMDAIoE +AwMAigYDAwCKDjAKAwMAihUDAwCKFjAKAwMAiiUDAwCKJgMDAYooAwMAijADAwGK +PgMDAIpCAwMAikYDAwCKUQMDAIpgAwMAimQwCgMDAYpmAwMAimgDAwCKagMDAIp8 +AwQDioCIMAoDAwCKgwMDAIqEAwMAioYwCgMDAIq7AwMGioADAwCKwzAKAwMBisYD +AwGKyAMDAIrLMAoDAwCKzQMDAIrOMAoDAwCK1wMDAIrYMAoDAwCK3QMDAIrkMAoD +AwCK5wMDAYroMAoDAwKK9AMDAIr2AwMCivgDAwCK/TAKAwMAiwEDAwCLBDAKAwMB +iwYDAwCLCDAKAwMBiwoDAwGLGDAKAwMAixsDAwCLHgMDAIstAwMAiy8DAwCLMgMD +AIs2AwMAizowCwMDAIs/AwQHi0AAAwMAi0IDAwGLSgMDAItPAwMAi1MwCgMDAItZ +AwMAi1wwCgMDBYtgAwMAi2IDAwCLZDAKAwMAi2kDAwCLeDAKAwMBi3oDAwCLfAMD +AIuAAwMAi4UDBAWLisADAwCLjQMDAIuPAwMAi5EDAwCLlQMDAIuZMAoDAwKLnAMD +AIueAwMAi6ADAwCLojAKAwMCi6QDAwCLpgMDAIuuAwMBi7IDAwCLuAMDAIu/AwMA +i94wCgMDAIxNAwMAjE4wCgMDAoxUAwMAjFYwCgMDAIxdAwMAjF4DAwCMYQMDAIxp +AwMBjJYDAwCMpAMDAIymAwMAjLUDAwCMywMDAIznMAkDAgCNAwMBjVQwCgMDAI1X +AwMBjWQDAwCNaQMDAI1sAwMAjXEDAwCNcwMDAI19AwMAjYIwCgMDAY2GAwMAjYow +CgMDAI2PAwMAjZQDAwCNowMEB42kgDAKAwMAjakDAwCNrDAKAwMAja8DAwCNsAMD +AI3AAwQAjcEUAwQCjcFsAwQBjcHWAwMAjcIDAwCNxAMDAY3IAwMAjcsDAwCN0DAL +AwMBjeIDBAON4oADBACN4oswCwMEBI3ikAMDAI3kAwMAjecDAwCN7QMDAI3xAwMB +jfQwCgMDAI35AwMAjfoDAwGN/AMDAI3/AwQDjlsIAwQDjlt4AwQDjluYAwQHjpoA +AwQDjuogAwMAjvcDAwCPKQMDAI8vMAoDAwGPMgMDAY80AwMAj0EwCwMEB49cgAMD +AY9cAwMAj2EDAwCPYzAKAwMAj3UDAwCPdgMDAI95AwMAj34wCgMDAI+BAwMAj4ID +AwCPoTAKAwMAj6MDAwCPpAMDAI+nAwMAj6kwCgMDBI+wAwMAj7QDAwCPxAMDAI/N +AwMAj9IDAwCP2QMDAY/gMAoDAwCP6QMDAI/qAwMAj+0DAwCP7wMDAI/1AwMAj/wD +AwCQAgMDAJAEAwMBkBQDAwCQGAMDAJAbAwMAkCADAwCQKTAKAwMAkCsDAwCQLAME +ApAwPAMDAJA2AwMBkDgwCgMDAJA/AwMBkEADAwCQTAMDAJBSMAsDAwKQVAMEB5BW +AAMDAJBXAwMAkF8DAwCQYgMDAJB3AwMAkHoDAwCQfAMDAJB/AwMAkJEDAwGQpAMD +AJCtMAoDAwSQsAMDAZC0AwMAkMEDAwCQyAMDAJDMAwMAkM4DBAaQ0AAwCwMEB5DQ +gAMDAZDQAwMAkPgwCQMCAJEDAwCSADAKAwMBkgIDAwCSBAMDAJITAwMAkhUDAwCS +MAMDAJIyAwMAkjQwCgMDAJI7AwMAkjwDAwGSQgMDAJJGAwQBkkdeAwMAkkgDAwCS +SwMDAJJNAwMBklADAwCSVwMEA5JY6AMDAJJaAwMAkmEwCgMDApJkAwMAkm4DAwCS +cDAKAwMAkncDAwCSeAMDAJJ8AwMAkoUDAwCSiAMDAJKMAwMBkp4wCgMDAJKhAwMA +kqIDAwCSqQMDAZKsMAoDAwCSrwMDAZKwAwMAkrMDAwCSuQMDAJK8MAoDAwCSvwMD +AJLCMAoDAwGS0gMDAZLUAwMAktgwCgMDAJLbAwMAktwDAwCS4DAKAwMAkuMDAwCS +5AMDAJLqAwMAkvEwCgMDAJL3AwMBkvgDAwCS+zAJAwMAkv0DAgCSAwMAkwcwCgMD +ApMMAwMAkw4wCgMDAJMbAwMAkx4DAwGTIAMDAZMsAwMAkzQDAwCTNgMDAJM8MAoD +AwCTQwMDAJNEAwMAk0swCgMDAJNNAwMAk04wCgMDAZNSAwMAk1QwCgMDAZNWAwMB +k1gDAwCTWzAKAwMAk10DAwCTYDAKAwMBk2IDAwCTZAMDAJNmMAoDAwCTbwMDAJNw +AwMAk3cDAwGTegMDAJN9AwMAk38DBAeTh4ADAwGTjjAKAwMAk5MDAwCTmAMDAJOc +MAoDAwCToQMDApOgAwMAk6cwCgMDAJOrAwMBk6wDAwCTrwMDAZO0AwMAk7gDAwCT +ugMDAZO8AwMAk8EDAwGTxAMDAJPJAwMAk8wDAwCT0jAKAwMAk9UDAwOT0AMDAJPc +MAoDAwKT5AMDAZPsAwMAk/MwCgMDAZP6AwMAk/wDAwGUAgMDAJQGAwMAlDYDAwCU +OAMEAJQ7cwMDAJQ8AwMAlD8DBAKUQDgDAwCURQMDAJRHAwQFlEzgAwMAlE8wCgMD +AJRRAwMClFADAwCUWAMDAZRuMAoDAwGUdgMDApR4MAoDAwCUhwMDAJSIAwMAlIoD +AwCUjAMDAJSPAwMAlJQDAwCUlwMDAJSgAwMAlKkDAwCUsAMDAJS1AwMAlLkDAwCU +uzAKAwMClMQDAwCUxgMDAJTIMAoDAwCU+wMDAZT8AwMAlQADAwCVAwMDAJUbAwMA +lTEDAwCVOwMDAJU+AwMAlVEDAwCVWgMDAJVtAwMAlX4wCgMDApWEAwMAlYYwCgMD +AJWLAwMAlYwwCgMDAZWSAwMAlZQwCgMDAJWZAwMBlZwDAwCVqgMDAJWsMAoDAwCV +sQMDAZXEMAoDAwOVyAMDAZXoMAwDBAOV6ggDBAeV6gAwCgMDAJXrAwMDlfAwCgMD +AJX5AwMClfgDAwGV/gMDAJZqAwQClmvIAwMAlnADAwCWgAMEApaBCAMDAJaEAwMA +lowwCgMDAJaRAwMAlpIDAwCWrwMDAJayAwMBlswwCgMDAJbVAwMAltYDAwCW2QMD +AJbjAwMBluwDAwCW8QMDAJb0AwMAlvsDAwCW/jAJAwIAlwMDAJdkMAsDAwGXagME +BZdqgDAMAwQGl2rAAwQEl2rgAwMAl3MDAwCXeAMDAJd/AwMAl4EDAwCXhTAKAwMA +l4cDAwCXiAMDAZecAwMAl6oDAwCXrTAKAwMAl68DAwGXsAMDAJe0MAoDAwGXtgMD +AJe4AwMAl7sDAwCXvTAKAwMAl9MDAwCX1DAJAwMDl9gDAgOQAwMAmEIDAwCYRwMD +AJhJMAoDAwCYTQMDAJhOAwMAmFEwCgMDA5hYAwMAmFowCgMDAJhdAwMAmGADAwCY +aQMDAZhyAwMAmIYDAwCYjwMDAJiWAwMAmJgDAwCZAQMDAJkFAwMAmQ8DAwCZEQMD +AJkTAwMAmVgwCgMDAplcAwMAmWIDAwCZZDAKAwMCmWwDAwCZbgMDAJlwMAsDAwOa +CAMEBJoIIAMEBpoIQAMDAZoOAwMAmiADAwCbBAMDAJstMAoDAwGbNgMDAJs4AwMA +m0IDAwCbSQMDAJtpMAoDAwCbgwMDAZuEAwMBm4gDBAabikADAwCbjAMDAJuRAwMA +m54DAwCbuQMDAJvAAwMAm8YDAwCbygMDAJvMAwMAm88wCgMDAJvRAwMAm9IDAwCb +3zAKAwMAm+MDAwCb5AMDAJvnAwMAm/UwCgMDAJv5AwMAm/oDAwCb/QMEBZv+IAMD +AJwKAwMAnA4wCgMDAJwRAwMAnBIDAwCcGQMDAJwcAwMAnCMDAwCcKwMDAZwwMAoD +AwCcMwMDAJw0AwMAnDYDAwCcOgMDAJw9AwMAnEMDAwCcUwMDAJxqMAoDAwGccgMD +AJx0AwMAnHYDAwCchQMDAJyHAwMAnJQDAwCcljAKAwMAnRcDAwGdHDAKAwMAnVMD +AwCdVAMDAJ1YAwMAnV4DAwGdYAMDAJ1jAwQDnXjgMAsDBAKdeOwDAwCdeAMDAZ18 +AwMAnYEDAwCdiAMDAJ2KAwMAnYwDAwCdkDAKAwMAnZ0DAwWdgDAKAwMAnaEDAwCd +pDAKAwMAnacDAwGdqDAKAwMAnasDAwGdrAMDAJ2xAwMBnbQDAwCdugMDAJ2+AwMA +ncEDAwCdyAMDAJ3LAwMAneQDAwCd5wMDAZ3sAwMAnfMDAwCd9wMDAJ35AwMCniQw +CgMDAJ4pAwMCnigDAwGeLjAKAwMAnjEDAwCeMgMDAJ46AwMAnjwDAwCeQAMDAZ5C +AwMAnksDAwCeWgMDAJ5cAwMAnl4DAwCeYwMDAJ5mAwMAnmkwCgMDAJ5tAwMAnm4D +AwCecAMDAJ53AwMCnnwDAwCegQMDAJ6DAwMAnoUDBASejBADBAaejEADAwCejwME +BJ6SgDAKAwMCnpQDAwCelgMDAJ6YAwMAnpwDAwCeojAKAwMBnqYDAwGeqDAKAwMC +nqwDAwGetDAKAwMBnr4DAwGexAMDAJ7YAwMAntoDAwCe3AMDAJ7fMAoDAwCe4QMD +Ap7gMAoDAwGe5gMDAJ7qMAoDAwOe+AMDAJ76MAoDAwCe/wMDAJ8AMAoDAwCfBwMD +AJ8IAwMAnwwDAwCfDwMDAJ8UAwMBnxYDAwCfGTAKAwMAnx0DAwWfAAMDAJ8iAwMA +nyYDAwCfLgMDAZ8yAwMAnzoDAwCfPAMDAJ9FAwMAn0gDAwCfUQMDAJ9UAwMAn1YD +AwGfXAMDAJ9fAwMBn2QwCgMDAJ9nAwMAn2gDAwCfawMDAJ9tAwMAn3IDBAOfdcAw +DAMEAZ91ygMEBJ91wAMDAJ96AwMAn4IDAwCfhgMEBZ+HgAMDAJ+QMAoDAwGfkgMD +AZ+UMAoDAwCflwMDAJ+YAwMAn5oDAwCfnAMDAJ+gAwMAn6IwCgMDAJ+nAwMAn6gD +AwGfqgMDAJ+tMAoDAwCfswMDAJ+0AwMAn74wCgMDAJ/BAwMCn8ADAwCfxQMDAJ/I +AwMAn80DAwCf0gMDAJ/VAwMBn9gDAwCf2wMDAJ/gAwMAn+gDAwGf7AMDAJ/vAwMA +n/EDBAOf8ggDBAaf8kADBASf8uADAwGf9DAJAwMAn/0DAgWAMAoDAwCgBQMDAKAG +AwMBoAgDBAKgE1wDBAKgE7QDBAOgFGADBAKgFGwDBASgFJADBAGgFNYDBACgFOUD +BAGgFPgDAwCgJgMDAKAoMAoDAwKgLAMDBqAAMAoDAwGgQgMDAKBEAwMBoEYDAwCg +SwMDAKBOAwMAoFADAwCgVQMDAKBcMAoDAwCgYQMDAKBkMAoDAwCgZwMDAKBoAwMA +oHIDAwCgtAMEBKDKEAMDAaDSMAoDAwCg1QMDAKDWMAoDAwOg2AMDAaDcAwMAoOQD +BAag50ADBACg7hUDBAKg7iQDBAKg7jQDBAGg7jwDBAKg7mADBASg7nAwCgMDAaEC +AwMBoQQDAwGhCAMDAKEMAwMAoREDAwChFAMDAKEXAwMAoRsDAwChHgMDAKElMAoD +AwChKQMDAKEqAwMAoTAwCgMDAqE0AwMAoTYDAwChOwMDAKE+AwMAoUMwCgMDAaFG +AwMAoUoDAwChTAMDAKFOMAoDAwChUwMDAKFcMAoDAwOhaAMDAKFqMAoDAwGhbgMD +AKFwAwMAoXQDAwChhgMDAKGTAwMAoZwDAwChngMDAKHKAwMAodoDAwCh5jAKAwMA +ofsDAwCh/AMDAKILAwQDogzIAwMAog0DAwCiFQMDAKIXMAoDAwCiGQMDAKIaAwMA +oiYDAwCiVgMDAKKFAwQHoo6AAwQBotiKAwQCotn4AwQDotpYAwQCotqwAwQDotzw +MAwDBAOi3lgDBACi3loDBAKi9DQDBAKi9cwDBAKi+MQDBAKi+tgDBAOi+yADBAKi +/8QDAwCjAQMDAKMDAwMAowUDAwCjCQMDAKMiMAoDAwGjPgMDAaN0AwMAo3cwCgMD +AqOcAwMEo6ADAwCj8jAJAwICpAMDAKQoAwMApDAwCgMDAKQ7AwMBpDwDAwCkUQME +B6RdgDAKAwMBpH4DAwSkgAMDAKSxAwMApNcDAwClTgMEBKVU0AMDAKVyAwMApcAD +AwCl2gMDAKXeAwMDpggDBAemMYADAwCmVwMDAKdRMAsDBAGnVkIDAwOnUAMDAKdi +AwQHp2SAAwMAp28DBAWnoAADAwCnqAMDAKesAwMAp8sDAwCn6QMDAKgBAwMAqIsD +BAeolQADBAGolfgDAwCouwMEAaj1xAMDBakgAwQHqZQAAwQEqgpwAwQHqhGAMAwD +BACqJcsDBACqJc4DAwCqPAMEB6plgAMEB6pmgAMEB6qFAAMDAarsAwMAqv8wCgMD +BKsQAwMBqyADBAesUIADBAOsZ1gDBAOs8QAwDAMEA6zxKAMEA6zxMAMEA6zxQAME +AqzxVAMEBKz/AAMEBKz/YAMEA6z/iAMEBKz/wAMEBKz/4AMEA6z/+AMEBq3UwAME +Aq3WyAMEA63qgAMEBK30kAMEBq35AAMEA63/kAMEBq6MAAMEB69ugDAKAwIEsAME +A7BvMDAMAwQAsG85AwQEsHOgMAwDBAOwc7gDBAewegAwCgMEBrB6wAMCALAwCgMC +AbIDBASy7kAwCgMEBbLuYAMCALIDAwC06jAKAwIAuQMEArkIYDAMAwQDuQhoAwQC +uRTYMAwDBAW5FOADBAO5HkAwDAMEArkeTAMEAbkm0DAMAwQCuSbUAwQCuVrwMAwD +BAO5WvgDBAO5ZCAwDAMEArlkLAMEALlpBjAMAwQDuWkIAwQFuZIAMAwDBAK5kiQD +BAK5qWgwDAMEBLmpcAMEBLmrwDAMAwQCuavUAwQCubAwMAwDBAO5sDgDBAS5soAw +CgMEArmylAMCAbgwCgMCArwDBAe8gwAwCwMDAryEAwQEvNGAMAwDBAO80ZgDBAa8 +1gAwCgMEBLzWUAMCALwwDAMEAsAFHAMEAMAFHgMEAMAFJAMEAMAFMgMEAMAFOzAM +AwQAwAU9AwQAwAU+AwQAwAVhAwQAwAWOAwQAwAWRAwQAwAWiAwQAwAXvAwQAwAX+ +AwQAwAwBAwQAwAwvAwQAwAw2AwQBwAxIAwQAwAxNAwQAwAxRAwQAwAxgAwQAwAxj +MAwDBAbADMADBADADMIwDAMEAMAM2QMEAMAM2jAMAwQAwAznAwQAwAzoAwQAwAzr +AwQAwAz3AwMAwA8wDAMEAMAQewMEAMAQpjAMAwQAwBC3AwQAwBDKAwQAwBLDMAwD +BALAGhwDBATAGiAwDAMEAMAaaQMEAcAabDAMAwQAwBpvAwQAwBqAMAwDBADAGoUD +BAPAGoAwDAMEAcAamgMEAcAawAMEAMAa5wMEAMAa6gMEAsAa7DAMAwQCwBx8AwQC +wByAAwQAwB8OAwQAwB8XAwQBwB8aAwQAwB8fAwQAwB8oAwQAwB8+AwQAwB9mMAwD +BAHAH6YDBALAH6gDBADAH9MDBADAH+cDBADAH/wwDAMEAMAhDwMEAMAhEAMEAMAh +JDAMAwQAwCFXAwQEwCFgMAwDBADAIXEDBADAIXIwDAMEAcAhdgMEB8AhAAMEAcAh +gjAMAwQAwCGPAwQBwCGQMAwDBADAIZMDBADAIaYwDAMEAMAhqQMEAsAhqDAMAwQE +wCGwAwQAwCG2MAwDBAbAIcADBAPAIeAwDAMEAMAh6QMEBMAh4AMEAMAh/gMEAMAi +EwMEAMAiMgMEAMAiawMEAMAidAMEAMAiszALAwMAwCMDBALAIxAwDAMEAMAjPwME +AMAjSAMEAMAjWgMEAMAjXgMEAMAjbDAMAwQBwCOCAwQBwCOEAwQAwCOKAwQAwCOS +MAwDBADAI5UDBAHAI5gDBADAI6wwDAMEAMAjtwMEAMAjwDAMAwQAwCPFAwQAwCPG +MAwDBADAI80DBATAI8ADBADAI+UwDAMEBMAj8AMEAMAj9AMEAcAj9jAKAwMCwCQD +AwDAJjAMAwQAwChFAwQAwChQAwQAwCjkMAwDBADAKWcDBADAKYgwDAMEAsApjAME +AcApkAMEAMApkzAMAwQAwCmVAwQAwCmgAwQAwCnSAwQAwCnYAwQAwCnaAwQAwCnj +AwQAwCoBMAwDBAHAKioDBATAKiADBADAKjUwDAMEAMAqPwMEAcAqQAMEAMAqVwME +AMAqYQMEAMAqZAMEAMAqZjAMAwQAwCpxAwQAwCqEAwQAwCqPMAwDBALAKrQDBAHA +KsgDBADAKv0wDAMEAcArogMEAsArqDAMAwQGwCvAAwQAwCvEAwQAwCvSAwQAwCvU +AwQAwCvqMAsDAwLALAMEAsAsQDAMAwQAwCxHAwQAwCxaMAwDBATALPADBALALPgw +DAMEAsAv9AMEAcAv+AMEAMAwHwMEAMAwawMEAMAwkQMEAMAw4AMEAMAw5wMDAMAx +AwQEwDMAMAsDAwLANAMEAMA0MgMEAMA0mDAMAwQAwDSfAwQBwDSgMAwDBADANN0D +BAXANMAwDAMEAMA0/QMEAMA0/jAMAwQAwDVnAwQAwDVoMAwDBADANh8DBADANjQw +DAMEAcA2NgMEAMA2UAMEAMA2aAMEAMA2cTAMAwQAwDZzAwQAwDZ4AwQAwDZ6MAwD +BADANn0DBADANoADBADANoQDBADANoswDAMEAMA2jQMEAcA23AMEAMA24QMEAcA2 +9AMEAMA2/gMEAMA3VAMEAMA3WQMEAMA3ZQMEAMA3aQMEAMA3bQMEAMA3cwMEAMA3 +gQMEAMA3hAMEAMA3vAMEAMA3wQMEAMA3xQMEAMA31AMEAMA39DAMAwQCwDocAwQC +wDogMAwDBADAOikDBAHAOlgDBADAOsUDBADAOtowDAMEAcA64gMEAcA65AMEAMBA +HAMEAcBALAMEAsBAZAMEAMBAfQMEAMBAyjAMAwQAwEEzAwQAwEFGMAwDBALAQVwD +BADAQV4DBADAQWAwDAMEAMBBgwMEAMBBhAMEAMBBizAMAwQEwEGQAwQAwEGSAwQA +wEGZMAwDBADAQbcDBAHAQcQwDAMEAMBB2wMEAMBB5AMDAMBCMAwDBADAQwMDBADA +QwQDBADAQycDBADAQysDBADAQy8DBADAQzIDBADAQzQDBADAQzcDBADAQzoDBADA +Q0wDBADAQ08DBADAQ1cDBADAQ14wDAMEAsBDZAMEAMBDaAMEAMBDhwMEAMBDpwME +AMBDqjAMAwQAwEO9AwQAwEPQAwQAwEPaAwQBwEPcAwQAwEPfAwQAwEP5MAsDAwLA +RAMEAsBEEAMEAMBEFzAMAwQAwEQfAwQCwEQwMAwDBALAREwDBALARGgwDAMEAMBE +lwMEAcBEmDAMAwQAwESlAwQAwESqAwQAwESuAwQAwESwAwQAwES2AwQAwES6AwQA +wETRMAwDBADARNMDBADARNgDBADARN0DBADAROADBADAROYwDAMEAcBE+gMEAMBE +/AMEAMBE/jALAwMBwEYDBAPARnAwDAMEAMBGhQMEAMBGhgMEAMBGiDAMAwQCwEaM +AwQFwEaAAwQDwEbAAwQAwEbyAwMAwEcwDAMEAMBJEwMEAMBJFDAMAwQBwEkiAwQA +wEksAwQAwEniAwQAwEnlMAwDBAHATAYDBALATCAwDAMEAMBMewMEAMBMhDAMAwQB +wEyGAwQAwEysAwQAwEywMAwDBADATPEDBADATPgDBADATQsDBAHATXIDBALATXgw +DAMEAsBNhAMEAMBNigMEAcBNjAMEAcBQFDAMAwQAwFAfAwQAwFAqAwQAwFAuAwQA +wFAzAwQAwFE7MAwDBADAUT0DBADAUT4DBADAUW0DBADAUXkDBADAUXsDBADAUaAw +DAMEAcBRtgMEAMBRuAMEAMBRwgMEAMBR5gMEAMBR6gMEAMBSeQMEAMBSfAMEAMBS +fwMEAMBSmTAMAwQAwFKdAwQAwFKeAwQAwFLWAwQBwFLcAwQAwFLxMAsDAwDAUwME +AMBTZAMEAMBTZgMEAMBToAMEAMBTpQMEAMBTyAMEAMBTygMEAMBT2AMEAMBT3zAM +AwQAwFPlAwQAwFPmAwQAwFQFAwQAwFQNAwQAwFQPAwQAwFQbAwQAwFQeAwQBwFQg +AwQAwFQ+MAwDBADAVEsDBADAVFQDBADAVFcwDAMEAcBUWgMEAsBUYDAMAwQAwFRl +AwQBwFRsMAwDBADAVH8DBADAVJwDBADAVKYDBADAVK0wDAMEBMBUsAMEBMBUwAME +AMBU1AMEAcBU3DAMAwQBwFTiAwQBwFTkMAwDBADAVPUDBAPAVPADBADAVgsDBADA +Vg4DBADAVhIDBADAVhkDBADAVhsDBADAVlkwDAMEAMBWfQMEB8BWAAMEAMBWhjAM +AwQAwFaJAwQAwFaKAwQAwFajAwQBwFamAwQAwFapAwQAwFb+AwMAwFcDBADAWAED +BADAWAQwDAMEAMBYCQMEAMBYCgMEAMBYETAMAwQAwFgXAwQAwFgYMAwDBADAWFMD +BADAWFQDBADAWFYwDAMEAMBYYQMEAMBYYgMEAMBYbAMEAMBYdgMEAMBYewMEAMBY +gAMEAMBYggMEAMBYhQMEAMBYxAMEAMBYzAMEAcBY7jAMAwQBwFj6AwQAwFj+AwMA +wFkDBAHAW4wDBADAW7EDBADAW7oDBADAW70DBADAW78DBADAW8cDBADAW8kDBADA +W9MwDAMEAcBb1gMEAcBb6DAMAwQCwFvsAwQDwFvwAwQAwFxWAwQAwFxeMAwDBAPA +XGgDBADAXGoDBAHAXGwDBADAXHQwDAMEAMBcfQMEAsBciDAMAwQAwFyNAwQBwFyY +MAwDBADAXJsDBADAXJwDBADAXNgDAwDAXQMEAMBeGAMEAMBeHDAMAwQAwF45AwQA +wF46MAwDBADAXkMDBADAXkQDBADAXkwDBADAXk4wDAMEAMBebwMEAcBedDAMAwQC +wF6cAwQCwF6gAwQAwF6sMAwDBADAXq8DBAPAXsADBADAXtQDBADAXt0DBADAXuID +BADAXukDBADAXusDBADAXu8DAwDAYgMEAMBkEjAMAwQAwGQXAwQBwGQYAwQAwGQ0 +AwQAwGQ9AwQAwGQ/AwQAwGROAwQCwGRgMAwDBAHAZGYDBAHAZIQwDAMEAMBkhwME +AMBkjAMEAMBkkAMEAMBkmgMEAMBlAQMEAMBlBAMEAMBlCAMEAMBlCwMEAMBlHAME +AMBlIgMEAMBlSzAMAwQAwGVRAwQAwGVaMAwDBADAZW8DBADAZXIDBADAZXYDBADA +ZYkwDAMEAMBloQMEAMBlqAMEAMBlqgMEAMBlsDAMAwQAwGWzAwQAwGW0AwQAwGXA +MAwDBADAZcUDBADAZcYDBADAZfwDBADAZgEwDAMEAcBmBgMEAMBmCDAMAwQAwGYR +AwQBwGZQAwQAwGZZAwQAwGZfMAwDBAHAZpIDBAHAZrADBADAZtYDBAHAZuAwDAME +AMBm4wMEAcBm5AMEAMBnAgMEAMBnBwMEAMBnDgMEAMBnFAMEAMBnFzAMAwQAwGcb +AwQAwGcoMAwDBADAZ1UDBADAZ3QwDAMEAMBniQMEAsBniAMEAMBnkwMEAMBoFwME +AcBoHDAMAwQAwGgjAwQBwGgkAwQAwGgpAwQAwGgwAwQAwGg1MAwDBADAaDcDBADA +aDoDBADAaEgDBADAaE0DBADAaFIDBADAaIwDBADAaI4DBADAaJMDBAHAaJowDAME +AMBopwMEAMBoqAMEAMBo7gMEAMBo9QMEAMBo+AMEAMBo+wMEAMBpSwMDAMBqAwQA +wGsCAwQBwGsEMAwDBADAawsDBAHAawwwDAMEAMBrMwMEAMBrZAMEAMBrbgMEAMBr +cjAMAwQBwGt6AwQBwGuAAwQAwGuEAwQAwGuoAwQAwGuuMAwDBADAa7EDBADAa7ID +BADAa7swDAMEA8BryAMEAcBr6DAMAwQAwGvrAwQAwGvsMAwDBADAbBcDBAHAbDAw +DAMEAMBsMwMEAMBsXAMEAcBsZDAMAwQAwGxrAwQAwGxsMAwDBAHAbHIDBAHAbHgw +DAMEAMBsfQMEAMBsfjAMAwQHwGyAAwQAwGyuMAwDBADAbMMDBADAbNYDBADAbOoD +BADAbO4wCwMDAMBtAwQAwG0sMAwDBAHAbS4DBADAbUowDAMEAsBtTAMEAsBtWDAM +AwQBwG1eAwQAwG1iMAwDBALAbWQDBADAbWYwDAMEAMBtaQMEA8BtcDAMAwQAwG15 +AwQBwG3wMAsDBADAbfMDAwHAbAMEAMBvIQMEAMBvJwMEAMBvLDAMAwQAwG8vAwQA +wG8wAwQAwG9YAwQAwG9lMAwDBADAb2cDBADAb2gDBAHAb3wDBADAb38DBADAb/ww +DAMEAcBwHgMEAMBwIAMEAMBwLQMEAMBwMQMEAMBwPTAMAwQBwHBGAwQEwHBAMAwD +BAHAcGIDBADAcGQDBADAcMwDBADAcM4DBADAcNAwDAMEAMBw1QMEAMBw1gMEAMBw +9wMEAMBw/jAKAwMAwHEDAwDAdgMDAMB5MAwDBADAegEDBADAeoIwDAMEAMB6jQME +AMB6kjAMAwQAwHqXAwQAwHqqAwQAwHrWMAwDBAPAetgDBADAeuowDAMEAcB67gME +AMB68gMEAMB6/jAMAwQAwHwZAwQAwHwcAwQAwHwgAwQAwHwnAwQAwHwuAwQAwHxw +MAwDBADAfHMDBADAfHQDBADAfJswDAMEAcB8qgMEAsB82AMEAMB86zAMAwQAwHzt +AwQBwHz0MAwDBADAfPcDBADAfPgwDAMEAcB8+gMEAMB8/gMDAMB9MAwDBADAfgED +BADAfkAwDAMEAMCBAQMEAcCBPAMEAMCBUAMEAMCBVwMEAMCBYgMDAMCCAwQAwIMU +MAwDBADAgxkDBADAgxoDBADAg08DBADAg1kDBADAg2ADBADAg2wDBADAg4QwDAME +AMCECQMEAsCECAMEAMCEIgMEAMCENQMEAMCENwMEAMCEYwMEAMCE7wMEAcCE9AME +AMCE/AMEAMCFDwMEAMCFHAMEAMCFIAMEAMCFJDAMAwQAwIU1AwQDwIUwAwQAwIU6 +AwQAwIVAAwQCwIVsAwQAwIV5AwQAwIWDAwQAwIX0AwMAwIYwDAMEAMCHBwMEAcCH +JAMEAMCHLjAMAwQAwIczAwQBwIc0AwQAwIc/AwQAwIdCAwQAwIdEAwQAwIdSAwQA +wIdkAwQAwIeBAwQAwIeFAwQAwIePMAwDBADAh5EDBADAh6gDBADAh68DBADAh7sD +BADAh9sDBADAh+EwDAMEAMCH5wMEAMCH6jAMAwQAwIf9AwQAwIf+AwQAwIgHAwQA +wIgJAwQBwIgSAwQAwIgXMAwDBADAiB0DBAXAiAADBAHAiCgDBADAiDEwDAMEAMCI +MwMEAMCINAMEAMCIPTAMAwQAwIhHAwQAwIhmMAwDBAHAiJoDBADAiJwwDAMEAMCK +AQMEAMCKCAMEAMCKVjAMAwQAwIppAwQBwIp0MAwDBADAipsDBADAip4DBADAircD +BADAisADBADAiswwDAMEAsCK5AMEAMCK6AMEAMCK+AMEAMCLTgMEAcCMAgMEBsCQ +ADAMAwQBwJBKAwQBwJBMAwQHwJEAAwQCwJHgAwQAwJJ1AwQAwJJ3MAwDBADAknsD +BADAkn4DBADAkoQwDAMEAcCShgMEAcCSjAMEAMCSmDAMAwQAwJKjAwQAwJKqMAwD +BALAkqwDBADAkrYDBADAkrkDBADAkrsDBADAksEDBADAkswwDAMEAMCS4wMEAMCS +5DAMAwQAwJLpAwQAwJLqAwQBwJLuAwQAwJLyAwQAwJMXAwQAwJMiAwQAwJMkAwQA +wJMqAwQCwJNMAwQAwJONAwQAwJOWAwQAwJObAwQAwJPUMAwDBADAk9cDBAHAk9gD +BADAk9sDBADAk+QDBADAk/cDBADAk/swDAMEAMCUIQMEAMCUXAMEAMCUZwMEAcCU +pjAMAwQAwJSxAwQAwJS6MAwDBAbAlMADBADAlMIwDAMEAcCUxgMEAMCU2AMEAMCU +3AMEAMCVAwMEAMCVBQMEAMCVDwMEAMCVEwMEAMCVGzAMAwQAwJUdAwQBwJUgAwQA +wJUjAwQAwJUpAwQAwJU5MAwDBADAlTsDBADAlTwwDAMEAMCVTQMEBMCVQAMEAMCV +YgMEAMCVZAMEAMCVZgMEAcCVbjAMAwQAwJV1AwQBwJV4AwQAwJV+AwQAwJXjAwQA +wJXoAwQAwJXuAwQAwJYUMAwDBAHAljoDBADAlkgwDAMEAMCWSwMEAMCWTDAMAwQB +wJZOAwQAwJZUAwQAwJZZAwQAwJZcAwQAwJZeAwQAwJZoAwQAwJZqAwQAwJZ8AwQA +wJaMAwQAwJaSMAwDBADAlrEDBADAlrgwDAMEAsCWvAMEAMCWvjAMAwQGwJbAAwQA +wJbGMAwDBADAlssDBAHAlswDBAHAltADBADAlt8wDAMEAMCW4wMEAcCW6AMEAMCW +7gMEAMCW+AMEAMCW/AMEAMCW/gMEAMCYBgMEAMCYDgMEAMCYEQMEAcCYGgMEAMCY +KgMEAMCYLDAMAwQAwJgvAwQCwJgwAwQAwJg2MAwDBADAmD0DBAbAmAADBADAmEQD +BADAmFIDBADAmGIwDAMEAMCYbwMEAMCYcAMEAMCYegMEAMCYfAMEAMCYjQMEAMCY +lwMEAMCYnAMEAcCYpgMEAMCYrgMEAsCYuAMEAMCY8QMEAMCY9DAMAwQAwJj9AwQA +wJj+AwQBwJkCAwQAwJkNAwQBwJkSAwQAwJlZAwQAwJl0AwQAwJl/AwQAwJmZAwQA +wJmmAwQAwJmoAwQAwJmrMAwDBADAma0DBADAmbYDBAHAmbwDBADAmcIDBADAmdUw +DAMEAMCbAQMEAMCbBgMEAMCchAMEAMCcogMEAMCcpwMEAMCc0gMEAMCc1QMEAMCc +2QMEAMCc4wMEAMCc7wMEAMCc+DAMAwQAwJ0BAwQCwJ0AMAwDBAPAnQgDBAHAnRAD +BADAnYEwDAMEAMCdpQMEAMCdrAMEAMCdrgMEAMCdsAMEAMCduQMEAMCduwMEAMCd +vQMEAcCfJgMEAMCfRgMEAMCfSQMEAMCfTQMEAcCfVAMEAMCfWgMEAMCfXzAMAwQA +wJ9jAwQDwJ9gAwQAwJ9pAwQBwJ9sAwQAwJ92MAwDBADAn3kDBADAn3oDBADAoAoD +BADAoA8wDAMEAMCgFQMEA8CgEAMEAMCgGwMEAMCgIQMEAMCgJQMEAMCgQQMEAMCg +QzAMAwQAwKBfAwQAwKBgAwQAwKBqMAwDBADAoG0DBADAoG4DBADAoHsDBADAoH4D +BAHAoI4DBADAoJgDBADAoJwDBADAoKADBADAoKwwDAMEAMCgsQMEAsCgsAMEAcCg +wgMEAcCg4DAMAwQAwKDnAwQBwKDoMAwDBADAoPUDBAHAoPgwDAMEAMCg+wMEAMCg +/AMEAcChBgMEAcChQAMDAMCiMAwDBAXAoyADBAXAo4ADAwLApDAMAwQAwKsBAwQB +wKsEMAwDBAfAq4ADBAPAq8ADBADArOgDBADArP0wDAMEAMCtAQMEAMCtBAMEA8Ct +gDAMAwQGwK5AAwQAwK5EAwQBwK8OAwQEwK8gAwMAwLAwDAMEBMC7EAMEAcC7GAME +AMC8CjAMAwQAwLw/AwQBwLxAAwQAwLxFAwQAwLxgAwQAwLxpAwQBwLx0MAwDBADA +vHkDBADAvHoDBADAvH0DBADAvH8DBADAvIEDBADAvIQDBADAvIgDBADAvJEwDAME +AMC8nQMEAMC8ngMEAMC8uwMEAMC8vTAMAwQAwLzpAwQBwLzsMAwDBAHAvPIDBADA +vPgDBADAvQEDBALAvQgDBADAvQ4DBADAvRcDBADAvSkwDAMEAMC9MwMEAMC9NAME +AMC9NwMEAMC9QjAMAwQAwL1FAwQAwL1GAwQAwL1JAwQAwL1MAwQAwL13AwQAwL2X +AwQAwL2aAwQAwL2dAwQAwL2gMAwDBAHAvaYDBADAvaoDBAHAvcoDBADAvfsDBADA +viwDBAHAvjoDBADAvkADBADAvkMDBADAvkUDBADAvl8wDAMEAMC+gQMEAMC+hDAM +AwQAwL6tAwQAwL6uAwQBwL62MAwDBAHAvr4DBAHAvsAwDAMEAMC+yQMEAMC+yjAM +AwQAwL7pAwQAwL7sAwQAwL7wAwQAwL7yMAwDBADAvvcDBAHAvvgDAwDAwgMEAMDD +AQMEAMDDCAMEAcDDKgMEAMDDSAMEAMDDYjAMAwQAwMNpAwQAwMNqAwQAwMNuMAwD +BALAw3QDBADAw3YwDAMEAcDDhgMEAMDDlDAMAwQAwMO3AwQAwMO4AwQAwMPDAwQA +wMPsMAwDBADAxAEDBALAxJgDBATAxxADBADAy1ADBAHAy2wDBADAy+MwDAMEAMDO +TQMEAcDOUAMEAMDOVjAMAwQBwM7eAwQAwM7iAwQAwM8OAwQAwM8fMAwDBADAz40D +BADAz44DBADAz8QDBADA50MDBADA51IwDAMEAMDuAQMEAMDuCgMEAMD1mAMEAMD1 +qQMEAMD14TAMAwQAwPcBAwQAwPcKMAwDBADA+z0DBAHA+0ADBADA++IDBADA++Yw +CgMCAMEDBADBEdYwDAMEA8ER2AMEA8ET4DAMAwQCwRPsAwQBwSmQMAwDBALBKZQD +BAbBUgAwDAMEBcFSYAMEBcFSwDAKAwMAwVMDAwDBXjAMAwQHwV+AAwQAwWwWAwQC +wWwYMAwDBADBbB0DBAHBbNQwDAMEAMFs1wMEAsFs+DALAwMAwW0DBAHBbUAwDAME +AsFtRAMEA8FuYDALAwQBwW5qAwMEwWADAwDBcTAMAwQFwXIgAwQFwXJAMAwDBAXB +cqADBAXBcwAwDAMEB8FzgAMEBcF0AAMEBsF0gAMEBsF1ADALAwQFwXVgAwMAwXYw +CwMEB8F3gAMDAcF4MAsDAwLBfAMEAMG8BjALAwQDwbwIAwMAwbwwDAMEAcG9QgME +B8G9ADAMAwQAwb2BAwQAwcIAMAwDBAHBwgYDBAXBwgADBAXBwmAwDAMEAMHCgQME +BcHCgDAMAwQGwcLAAwQBwd3YMAsDBADB3dsDAwDB4gMEBsHjQDAMAwQAweOBAwQF +wgbAMAwDBADCBuEDBAbCCQAwDAMEAcIJQgMEAcIJUDAMAwQCwglUAwQAwiO+MAwD +BAbCI8ADBAXCT0AwCwMEB8JPgAMDAMJaMAsDAwLCXAMEBcLBAAMEBsLBQDAMAwQF +wsHgAwQGwsyAMAoDAwDCzQMDAMLeMAwDBAXC32ADBAXC34AwDAMEBsLfwAMEBMMY +QDAMAwQDwxhYAwQGwxiAMAwDBAXDGOADBAHDJ9gwCwMEAsMn3AMDAMMqMAwDBAXD +KyADBALDgAAwDAMEA8OACAMEBcOmwDALAwMAw6cDBAXDp4AwDAMEBMOnsAMEBsPK +ADAMAwQFw8pgAwQDw+pwMAwDBALD6nwDBAPD6qAwDAMEAMPqqQMEAMPquDAMAwQB +w+q6AwQCw+r4MAsDAwDD6wMEBcP2ADAKAwQGw/ZAAwICwAMEAMQBAzAMAwQAxAEF +AwQAxAEGAwQCxAFAMAwDBADEAUUDBADEAUYDBALEAgQwDAMEAcQDQgMEA8QDQAME +AMQDWwMEBcQPIAMEAsYLAAMEAMYRTQMEAMYRdTAMAwQCxhG0AwQAxhG2AwQAxhYz +MAwDBADGFl0DBAHGFmAwDAMEBcYkIAMEAMYkLgMEAsYtdAMEAMYzDDAMAwQAxjOP +AwQAxjOSAwQCxjQsAwQCxjccAwQDxllYAwQAxmOUAwQAxmPeAwQFxmlgMAwDBATG +hVADBAHGhVQDBADGhYwDBADGhc4DBADGheIwDAMEAMaHiQMEAMaHigMEAMaHpwME +AMaToDAMAwQAxpSxAwQAxpSyMAwDBAHGtJYDBAHGtJgDBADGzsUwDAMEA8bOyAME +AMbOygMEB8bwgAMEAccr9gMEAccw5gMDAMc1AwQDx1jQAwQEx1sQMAwDBAPHZwgD +BADHZwwDBAXH9wADBAPH9zgDBAXH+oADBADKAE0DBATLn1ADBAPLvjgDBALMCwAD +AwDMEgMEAcwwIAMEAMzh2gMEAM3JNwMEAM3TUwMEAc3c2AMEAM6nIQMEAs6+3AME +Bc7DIAMEBc784AMEBs9ZQAMEBc+WoAMEAs+u2AMEBc+yQAMEBs+0wAMEBM+9wDAM +AwQEz+VwAwQAz+V0MAwDBAHP5XYDBADP5XgwDAMEAc/legMEB8/lAAMEAtBSSAME +BtEqwAMEBdGigAMEBdHOAAMEAdHOJgMEBNHVMAMEBdH64DAMAwQA0fvDAwQB0fvE +AwQB0fv8AwQH1AAAMAwDBAXUAKADBAHUCOQwDAMEA9QI6AMEANQI8DAMAwQB1Ajy +AwQB1Aj8MAsDAwDUCQMEBdQMwDALAwMA1A0DBAXUFoAwDAMEBtQWwAMEBtQxADAM +AwQF1DFgAwQH1DQAMAwDBAXUNKADBAbUPAAwCwMEBdQ8YAMDBtQAMAwDBAfUQIAD +BATURYAwDAMEBdRFoAMEBtRVgDAMAwQF1FXgAwQF1FhAMAwDBAfUWIADBAHUXGQw +DAMEA9RcaAMEB9RfADALAwQF1F+gAwMF1EAwDAMEBdRgIAMEBtRkADAMAwQF1GRg +AwQF1GeAMAwDBAbUZ8ADBATUdSAwDAMEBtR1QAMEBdR6wDALAwMA1HsDBAfUgQAw +CgMDAdSCAwMA1NgwDAMEB9TZgAMEBtU3ADAMAwQH1TeAAwQG1YMAMAwDBAXVg2AD +BAXViEAwDAMEB9WIgAMEBtWTADAMAwQF1ZNgAwQF1ZZAAwQF1ZaAMAwDBAXVluAD +BAbVmAAwDAMEBdWYYAMEBdWaADAMAwQF1ZpgAwQF1Z6AMAwDBAbVnsADBAHVnwww +DAMEBNWfEAMEAtWfgDAMAwQD1Z+IAwQH1awAMAwDBAXVrKADBAXVs4AwDAMEBtWz +wAMEBdW1wDALAwMB1bYDBAXVwQAwDAMEBtXBQAMEBtXUgDAKAwMA1dUDAwDV9jAM +AwQF1fcgAwQH1f8AMAoDBAXV/6ADAgHUAwQB2C58AwQA2GPeAwQE2J5gAwQE2KxA +AwQG2NWAAwQF2PGAMAoDAgDZAwQE2Q5AMAwDBAXZDmADBAXZFMAwDAMEBNkU8AME +BNkVYDAMAwQH2RWAAwQH2R0AMAwDBATZHZADBATZHcAwCwMEBdkd4AMDAtkwMAsD +AwPZOAMEBdlAQDAMAwQE2UBwAwQG2U0AMAwDBATZTVADBAbZTgAwCwMEBNlOUAMD +ANl0MAsDBATZdRADAwDZijALAwMC2YwDBAPZk7AwDAMEBtmTwAMEBNmqgDALAwQF +2aqgAwMB2bAwCwMDANmzAwQE2ceAMAoDBAXZx6ADAgHYAwQC3J7EMGQEAgACMF4D +BQAgAQAFMA0DBAEgAQYDBQEgAQf4MA0DBQAgAQf7AwQCIAEIAwQCIAEUMAwDBAEg +ARoDBAEgAUADBAEgAUYwDAMEASABSgMEASABTAMEBCABUAMEBiADAAMDBCoAMIIG +oAYIKwYBBQUHAR0EggaSMIIGjqCCBoowggaGAgEHAgEcAgIAiQICAOAwCAICAPgC +AgD7AgIBBQICAR4CAgEgAgIBJgICAXcCAgF6AgICAQICAgUwCAICAhACAgIRAgIC +IAICAikCAgIvAgICNQICAk4CAgJRAgICnTAIAgICpwICAqgwCAICArcCAgK5MAgC +AgLFAgICxgICAsgCAgLPMAgCAgL4AgIC+QICAvwCAgL+MAgCAgMGAgIDDwICAxIw +CAICAxUCAgMWMAgCAgRNAgIEsAICBLMCAgS1AgIEvTAIAgIE0gICBNMCAgTZAgIE +4AICBOUCAgTpMAgCAgTzAgIE+wICBP8CAgUKAgIFETAIAgIFEwICBR0CAgUmAgIF +PjAIAgIFSAICBUkCAgYLMAgCAgZ1AgIGdgICBn8CAgaQMAgCAgarAgIGvgICBsEC +AgbEMAgCAgbKAgIGywICBs0CAgbUAgIG2DAIAgIG2gICBtwCAgbfAgIG5DAIAgIG +6gICBusCAgbuAgIG8AICBvQCAgcpMAgCAgcrAgIHLQICBzEwCAICBzkCAgc6MAgC +Agc9AgIHPjAIAgIHVQICB28wCAICB4ECAgeDAgIHhgICB4owCAICB48CAgejMAgC +AgeoAgIHqgICB68CAgfUAgIH3DAIAgIH4AICB+EwCAICB+oCAgftAgIH9DAIAgIH +9gICB/gCAgf7AgIH/QICB/8CAggBMAgCAggJAgIIWDAIAgIIYwICCGQwCAICCH4C +AgjhMAgCAgjmAgIJSQICCUwwCAICCVMCAgm4AgIJvjAIAgIJ4QICCeICAgntMAgC +AgnyAgIJ8wICChIwCAICChkCAgo2AgIKUwICClcCAgp7AgIKzjAIAgIK1QICCwYw +CAICCw4CAgs/AgILTwICC2UCAgtpAgIL8jAIAgIMCwICDCUCAgxPMAgCAgxSAgIM +hzAIAgIMiQICDRkwCAICDVQCAg1XAgIOKAICDwMwCAICD00CAg9OAgIQNDAIAgIR +NQICEU4wCAICEWkCAhFqAgIRrDAIAgIR7AICEe0CAhNuAgIT4TAIAgIVAQICFZ8w +CAICFaECAhX/AgIXswICF8UCAhgYAgIYsAICGQwwCAICGgACAho4MAgCAho6AgIa +3jAIAgIa4AICGv8CAh+dMAgCAiAAAgIhSzAIAgIhTQICIkEwCAICIkMCAiOoMAgC +AiOqAgIj/wICLE0CAi2MAgIvDjAIAgIwAAICMKYwCAICMKgCAjELMAgCAjENAgIz +pzAIAgIzqQICM/8CAjY3MAgCAjwAAgI8JjAIAgI8KAICPHIwCAICPHQCAj1ZMAgC +Aj1bAgI9uzAIAgI9vQICPdAwCAICPdICAj3ZMAgCAj3bAgI+WzAIAgI+XQICPrkw +CAICPrsCAj9VMAgCAj9XAgI/mzAIAgI/nQICP/8CAkksAgJK6gICS7ACAkvHMAgC +AlAAAgJQAzAIAgJQBQICUXkwCAICUXsCAlG/MAgCAlHBAgJSCjAIAgJSDAICUp8w +CAICUqECAlL5MAgCAlL7AgJTFjAIAgJTGAICUx0CAlMfMAgCAlMhAgJTjjAIAgJT +kAICU8swCAICU80CAlP/AgJWXAICWGMCAlibAgJayjAIAgJgAAICYJ8wCAICYKEC +AmC0MAgCAmC2AgJg0zAIAgJg1QICYOAwCAICYOICAmECMAgCAmEEAgJhHjAIAgJh +IAICYS0wCAICYS8CAmGaMAgCAmGcAgJiSjAIAgJiTAICYqEwCAICYqMCAmMRAgJj +EzAIAgJjFQICY8YwCAICY8gCAmPfMAgCAmPhAgJj5zAIAgJj6QICY/8CAmUYMAgC +AnAAAgJwCjAIAgJwDAICcBkwCAICcBsCAnDwMAgCAnDyAgJxojAIAgJxpAICcpkC +AnKbMAgCAnKdAgJy8zAIAgJy9QICczYwCAICczgCAnNnMAgCAnNpAgJzgjAIAgJz +hAICc60wCAICc68CAnPpMAgCAnPrAgJz/zAIAgJ4AAICeK8wCAICeLECAnkDAgJ5 +BTAIAgJ5GAICeVgwCAICeVoCAnoMMAgCAnoOAgJ7gjAIAgJ7hAICe/8wCgIDAIQA +AgMAi/8wCgIDAJgAAgMAm/8wCgIDAKAAAgMApY0wCgIDAKWPAgMAr/8wCgIDALgA +AgMAy/8wCgIDANwAAgMA4/8wCgIDAOgAAgMA7/8wCgIDAPIAAgMA8/8wCgIDAPuM +AgMA++8wCgIDAwAAAgMDNZs= +""" + + def setUp(self): + self.asn1Spec = rfc5280.Extensions() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.extns_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + oids = [] + for extn in asn1Object: + oids.append(extn['extnID']) + extn_value, rest = der_decoder( + extn['extnValue'], + rfc5280.certificateExtensionsMap[extn['extnID']]) + + self.assertFalse(rest) + self.assertTrue(extn_value.prettyPrint()) + self.assertEqual(extn['extnValue'], der_encoder(extn_value)) + + self.assertIn(rfc8360.id_pe_ipAddrBlocks_v2, oids) + self.assertIn(rfc8360.id_pe_autonomousSysIds_v2, oids) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc8398.py b/tests/test_rfc8398.py new file mode 100644 index 0000000..b524831 --- /dev/null +++ b/tests/test_rfc8398.py @@ -0,0 +1,66 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc8398 + + +class EAITestCase(unittest.TestCase): + pem_text = "oCAGCCsGAQUFBwgJoBQMEuiAgeW4q0BleGFtcGxlLmNvbQ==" + + def setUp(self): + self.asn1Spec = rfc5280.GeneralName() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertIn(asn1Object['otherName']['type-id'], + rfc5280.anotherNameMap) + self.assertEqual(rfc8398.id_on_SmtpUTF8Mailbox, + asn1Object['otherName']['type-id']) + + eai, rest = der_decoder( + asn1Object['otherName']['value'], + asn1Spec=rfc5280.anotherNameMap[asn1Object['otherName']['type-id']]) + + self.assertFalse(rest) + self.assertTrue(eai.prettyPrint()) + self.assertEqual(asn1Object['otherName']['value'], der_encoder(eai)) + self.assertEqual(u'\u8001', eai[0]) + self.assertEqual(u'\u5E2B', eai[1]) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual( + rfc8398.id_on_SmtpUTF8Mailbox, asn1Object['otherName']['type-id']) + self.assertEqual(u'\u8001', asn1Object['otherName']['value'][0]) + + self.assertEqual(u'\u5E2B', asn1Object['otherName']['value'][1]) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc8410.py b/tests/test_rfc8410.py new file mode 100644 index 0000000..d6df485 --- /dev/null +++ b/tests/test_rfc8410.py @@ -0,0 +1,44 @@ +# +# 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 +import unittest + +from pyasn1.codec.der import decoder as der_decoder +from pyasn1.codec.der import encoder as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5208 +from pyasn1_modules import rfc8410 + + +class PrivateKeyTestCase(unittest.TestCase): + no_pub_key_pem_text = ("MC4CAQAwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwo" + "y/HU++CXqI9EdVhC") + + def setUp(self): + self.asn1Spec = rfc5208.PrivateKeyInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.no_pub_key_pem_text) + asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual( + rfc8410.id_Ed25519, asn1Object['privateKeyAlgorithm']['algorithm']) + self.assertTrue(asn1Object['privateKey'].isValue) + self.assertEqual( + "0x0420d4ee", asn1Object['privateKey'].prettyPrint()[0:10]) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc8418.py b/tests/test_rfc8418.py new file mode 100644 index 0000000..b5e8d3e --- /dev/null +++ b/tests/test_rfc8418.py @@ -0,0 +1,43 @@ +# +# 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 +import unittest + +from pyasn1.codec.der import decoder as der_decoder +from pyasn1.codec.der import encoder as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc8418 + + +class KeyAgreeAlgTestCase(unittest.TestCase): + key_agree_alg_id_pem_text = "MBoGCyqGSIb3DQEJEAMUMAsGCWCGSAFlAwQBLQ==" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.key_agree_alg_id_pem_text) + asn1Object, rest = der_decoder.decode( + substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual( + rfc8418.dhSinglePass_stdDH_hkdf_sha384_scheme, + asn1Object['algorithm']) + self.assertTrue(asn1Object['parameters'].isValue) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc8419.py b/tests/test_rfc8419.py new file mode 100644 index 0000000..3ad05cb --- /dev/null +++ b/tests/test_rfc8419.py @@ -0,0 +1,130 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc8419 + + +class Ed25519TestCase(unittest.TestCase): + alg_id_1_pem_text = "MAUGAytlcA==" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.alg_id_1_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(rfc8419.id_Ed25519, asn1Object['algorithm']) + self.assertFalse(asn1Object['parameters'].isValue) + self.assertEqual(substrate, der_encoder(asn1Object)) + + +class Ed448TestCase(unittest.TestCase): + alg_id_2_pem_text = "MAUGAytlcQ==" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.alg_id_2_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(rfc8419.id_Ed448, asn1Object['algorithm']) + self.assertFalse(asn1Object['parameters'].isValue) + self.assertEqual(substrate, der_encoder(asn1Object)) + + +class SHA512TestCase(unittest.TestCase): + alg_id_3_pem_text = "MAsGCWCGSAFlAwQCAw==" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.alg_id_3_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(rfc8419.id_sha512, asn1Object['algorithm']) + self.assertFalse(asn1Object['parameters'].isValue) + self.assertEqual(substrate, der_encoder(asn1Object)) + + +class SHAKE256TestCase(unittest.TestCase): + alg_id_4_pem_text = "MAsGCWCGSAFlAwQCDA==" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.alg_id_4_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(rfc8419.id_shake256, asn1Object['algorithm']) + self.assertFalse(asn1Object['parameters'].isValue) + self.assertEqual(substrate, der_encoder(asn1Object)) + + +class SHAKE256LENTestCase(unittest.TestCase): + alg_id_5_pem_text = "MA8GCWCGSAFlAwQCEgICAgA=" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.alg_id_5_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(rfc8419.id_shake256_len, asn1Object['algorithm']) + self.assertTrue(asn1Object['parameters'].isValue) + self.assertEqual(substrate, der_encoder(asn1Object)) + + param, rest = der_decoder( + asn1Object['parameters'], + asn1Spec=rfc5280.algorithmIdentifierMap[asn1Object['algorithm']]) + + self.assertFalse(rest) + self.assertTrue(param.prettyPrint()) + self.assertEqual(asn1Object['parameters'], der_encoder(param)) + self.assertEqual(512, param) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.alg_id_5_pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(rfc8419.id_shake256_len, asn1Object['algorithm']) + self.assertEqual(512, asn1Object['parameters']) + self.assertEqual(substrate, der_encoder(asn1Object)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc8479.py b/tests/test_rfc8479.py new file mode 100644 index 0000000..e5b135f --- /dev/null +++ b/tests/test_rfc8479.py @@ -0,0 +1,108 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc4055 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5958 +from pyasn1_modules import rfc8479 + + +class ValidationParmTestCase(unittest.TestCase): + pem_text = """\ +MIIE/gIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCpPwXwfhDsWA3q +jN2BWg1xfDjvZDVNfgTV/b95g304Aty3z13xPXAhHZ3ROW3pgPxTj9fiq7ZMy4Ua +gMpPK81v3pHX1uokC2KcGXbgbAq2Q8ClxSXgEJllRwDENufjEdV10gArt8NlIP0N +lota1kQUuI1DMsqc5DTIa35Nq4j1GW+KmLtP0kCrGq9fMGwjDbPEpSp9DTquEMHJ +o7kyJIjB+93ikLvBUTgbxr+jcnTLXuhA8rC8r+KXre4NPPNPRyefRcALLt/URvfA +rTvFOQfi3vIjNhBZL5FdC+FVAr5QnF3r2+cuDPbnczr4/rr81kzFGWrwyAgF5FWu +pFtB5IYDAgMBAAECggEAHZ88vGNsNdmRkfhWupGW4cKCuo+Y7re8Q/H2Jd/4Nin2 +FKvUPuloaztiSGDbVm+vejama/Nu5FEIumNJRYMeoVJcx2DDuUxO1ZB1aIEwfMct +/DWd0/JDzuCXB0Cu5GTWLhlz0zMGHXihIdQ0DtGKt++3Ncg5gy1D+cIqqJB515/z +jYdZmb0Wqmz7H3DisuxvnhiCAOuNrjcDau80hpMA9TQlb+XKNGHIBgKpJe6lnB0P +MsS/AjDiDoEpP9GG9mv9+96rAga4Nos6avYlwWwbC6d+hHIWvWEWsmrDfcJlm2gN +tjvG8omj00t5dAt7qGhfOoNDGr5tvJVo/g96O/0I8QKBgQDdzytVRulo9aKVdAYW +/Nj04thtnRaqsTyFH+7ibEVwNIUuld/Bp6NnuGrY+K1siX8+zA9f8mKxuXXV9KK4 +O89Ypw9js2BxM7VYO9Gmp6e1RY3Rrd8w7pG7/KqoPWXkuixTay9eybrJMWu3TT36 +q7NheNmBHqcFmSQQuUwEmvp3MQKBgQDDVaisMJkc/sIyQh3XrlfzmMLK+GlPDucD +w5e50fHl8Q5PmTcP20zVLhTevffCqeItSyeAno94Xdzc9vZ/rt69410kJEHyBO9L +CmhtYz94wvSdRhbqf4VzAl2WU184sIYiIZDGsnGScgIYvo6v6mITjRhc8AMdYoPR +rL6xp6frcwKBgFi1+avCj6mFzD+fxqu89nyCmXLFiAI+nmjTy7PM/7yPlNB76qDG +Dil2bW1Xj+y/1R9ld6S1CVnxRbqLe+TZLuVS82m5nRHJT3b5fbD8jquGJOE+e+xT +DgA0XoCpBa6D8yRt0uVDIyxCUsVd5DL0JusN7VehzcUEaZMyuL+CyDeRAoGBAImB +qH6mq3Kc6Komnwlw4ttJ436sxr1vuTKOIyYdZBNB0Zg5PGi+MWU0zl5LDroLi3vl +FwbVGBxcvxkSBU63FHhKMQw7Ne0gii+iQQcYQdtKKpb4ezNS1+exd55WTIcExTgL +tvYZMhgsh8tRgfLWpXor7kWmdBrgeflFiOxZIL1/AoGAeBP7sdE+gzsh8jqFnVRj +7nOg+YllJAlWsf7cTH4pLIy2Eo9D+cNjhL9LK6RaAd7PSZ1adm8HfaROA2cfCm84 +RI4c7Ue0G+N6LZiFvC0Bfi5SaPVAExXOty8UqjOCoZavSaXBPuNcTXZuzswcgbxI +G5/kaJNHoEcdlVsPsYWKRNKgPzA9BgorBgEEAZIIEggBMS8wLQYJYIZIAWUDBAIC +BCCK9DKMh7687DHjA7j1U37/y2qR2UcITZmjaYI7NvAUYg== +""" + + def setUp(self): + self.asn1Spec = rfc5958.OneAsymmetricKey() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + for attr in asn1Object['attributes']: + self.assertIn(attr['attrType'], rfc5652.cmsAttributesMap) + + if attr['attrType'] == rfc8479.id_attr_validation_parameters: + av, rest = der_decoder( + attr['attrValues'][0], + asn1Spec=rfc5652.cmsAttributesMap[attr['attrType']]) + self.assertFalse(rest) + self.assertTrue(av.prettyPrint()) + self.assertEqual(attr['attrValues'][0], der_encoder(av)) + self.assertEqual(rfc4055.id_sha384, av['hashAlg']) + + seed = univ.OctetString(hexValue='8af4328c87bebcec31e303b8f55' + '37effcb6a91d947084d99a36982' + '3b36f01462') + + self.assertEqual(seed, av['seed']) + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder( + substrate, asn1Spec=self.asn1Spec, decodeOpenTypes=True) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + for attr in asn1Object['attributes']: + self.assertIn(attr['attrType'], rfc5652.cmsAttributesMap) + if attr['attrType'] == rfc8479.id_attr_validation_parameters: + av = attr['attrValues'][0] + + self.assertEqual(av['hashAlg'], rfc4055.id_sha384) + + seed = univ.OctetString(hexValue='8af4328c87bebcec31e303b8f553' + '7effcb6a91d947084d99a369823b' + '36f01462') + + self.assertEqual(seed, av['seed']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc8494.py b/tests/test_rfc8494.py new file mode 100644 index 0000000..2951e39 --- /dev/null +++ b/tests/test_rfc8494.py @@ -0,0 +1,55 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc8494 + + +class CompresssedDataTestCase(unittest.TestCase): + pem_text = """\ +MIIBNqADAgEAMIIBLaADAgEZoIIBJASCASB4nG2P0U7CQBBF3/cr5l2K3YpSF5YA +bYmbWArtQsJjKVuogd1mO0T8e0ti1IjJZB4md07OHZbWnMbqkp/qo+oW5jSCWDqL +VCSpkBveg2kSbrg/FTIWcQRpJPlLmGYQzdci5MvlA+3Rx2cyREO/KVrhCOaJFLMN +n03E6yqNIEmDheS2LHzPG0zNdqw0dn89XAnev4RsFQRRlnW+SITMWmMGf72JNAyk +oXCj0mnPHtzwSZijYuD1YVJb8FzaB/rE2n3nUtcl2Xn7pgpkkAOqBsm1vrNWtqmM +ZkC7LgmMxraFgx91y0F1wfv6mFd6AMUht41CfsbS8X9yNtdNqayjdGF2ld4z8LcV +EiIPVQPtvBuLBxjW5qx3TbXXo6vHJ1OhhLY= + +""" + + def setUp(self): + self.asn1Spec = rfc8494.CompressedData() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual( + 0, asn1Object['compressionAlgorithm']['algorithmID-ShortForm']) + + cci = asn1Object['compressedContentInfo'] + + self.assertEqual( + 25, cci['unnamed']['contentType-ShortForm']) + self.assertEqual( + '0x789c6d8fd1', cci['compressedContent'].prettyPrint()[:12]) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc8520.py b/tests/test_rfc8520.py new file mode 100644 index 0000000..da615dc --- /dev/null +++ b/tests/test_rfc8520.py @@ -0,0 +1,115 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc8520 + + +class MUDCertTestCase(unittest.TestCase): + mud_cert_pem_text = """\ +MIIFODCCAyCgAwIBAgICEEAwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCQ0gx +DzANBgNVBAgMBlp1cmljaDERMA8GA1UEBwwIV2V0emlrb24xEDAOBgNVBAoMB0lt +UmlnaHQxIDAeBgNVBAMMF0ltUmlnaHQgVGVzdCA4MDIuMUFSIENBMB4XDTE5MDUw +MTE4MDMyMVoXDTE5MDUzMTE4MDMyMVowZzELMAkGA1UEBhMCQ0gxEzARBgNVBAgM +ClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEg +MB4GA1UEAwwXTGlnaHRidWxiMjAwMCwgU04jMjAyMDIwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCzntv6tCdkZWPUx+CK9A9PCgKF8zGCJwdU4eIjo0oe +A81i7iltOPnU416GJMEc2jGhlZPn2Rjjy8tPbyh1RVBfkgdq4UPWPnZPb+Gkq1c8 +X8zLRrMSWKqkSGOPENieDuQpzcrkMfj7dCPcxTcJ5Gluv1jEI7bxoZOZXjNxaFXi +vsaZWFub7b+5zDLWpvmpKDaeCU+gad7rWpRE/Hjh3FX8paW8KE/hMF/au4xX2Qj/ +rDwHSxgs3n8FtuFUELotSgL3Acy3aISmJILBx6XrSs3nLruZzamulwWupSryHo3L +U+GsOETiXwxiyrfOZo3aJNnWzlEvrYCQGyqd8Nd/XOENAgMBAAGjge8wgewwCQYD +VR0TBAIwADBABggrBgEFBQcBGQQ0FjJodHRwczovL3d3dy5vZmNvdXJzZWltcmln +aHQuY29tL0x1bWluYWlyZV8xNTAuanNvbjBdBggrBgEFBQcBHgRRME8xCzAJBgNV +BAYTAkNIMSswKQYJKoZIhvcNAQkBFhxhc2NlcnRpYUBvZmNvdXJzZWltcmlnaHQu +Y29tMRMwEQYDVQQDEwpFbGlvdCBMZWFyMB0GA1UdDgQWBBS00spi6cRFdqz95TQI +9AuPn5/DRjAfBgNVHSMEGDAWgBREKvrASIa7JJ41mQWDkJ06rXTCtTANBgkqhkiG +9w0BAQsFAAOCAgEAiS4OlazkDpgR4qhrq5Wpx6m3Bmkk5RkXnqey1yyhyfZlAGH7 +ewQiybkF3nN6at/TcNWMRfGBLhRrQn1h75KEXKlc18RDorj72/bvkbJLoBmA43Mv +xMF0w4YX8pQwzb4hSt04p79P2RVVYM3ex/vdok0KkouhLTlxzY7vhv1T8WGTVQHJ +k2EyswS2nFa/OtIkwruXqJj+lotdV2yPgFav5j9lkw5VbOztlfSKT7qQInVm+VBI +/qddz/LOYrls1A7KHzWkTvOwmvQBqI4e9xLjc3r8K4pZyMd7EsmepYmLOU+pfINf +/sEjliCluR65mKcKGiUa5J31pzbVpCr6FM/NGEjqpp6F+slyNC8YM/UlaJK1W9ZI +W7JAhmfil5z1CtQILFSnUh4VneTVOaYg6+gXr169fXUDlMM4ECnuqWAE2PLhfhI8 ++lY8u18rFiX0bNSiUySgxU3asCC92xNmvJHuL4QwiYaGtTne36NMN7dH/32nMKl+ +G3XA8cX8yZIrIkmWLBSji8UwOXwVhYovmbhHjaUMTQommxYv/Cuqi5nJUJfh5YJr +APeEK6fTYpPMiZ6U1++qzZDp78MRAq7UQbluJHh8ujPuK6kQmSLXmvK5yGpnJ+Cw +izaUuU1EEwgOMELjeFL62Ssvq8X+x6hZFCLygI7GNeitlblNhCXhFFurqMs= +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.mud_cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + extn_list = [] + for extn in asn1Object['tbsCertificate']['extensions']: + extn_list.append(extn['extnID']) + + if extn['extnID'] == rfc8520.id_pe_mudsigner: + mudsigner, rest = der_decoder( + extn['extnValue'], rfc8520.MUDsignerSyntax()) + + self.assertEqual(extn['extnValue'], der_encoder(mudsigner)) + + c = rfc5280.X520countryName(value="CH") + + self.assertEqual(mudsigner[0][0][0]['value'], der_encoder(c)) + + e = rfc5280.EmailAddress(value="ascertia@ofcourseimright.com") + + self.assertEqual(mudsigner[0][1][0]['value'], der_encoder(e)) + + cn = rfc5280.X520CommonName() + cn['printableString'] = "Eliot Lear" + + self.assertEqual(mudsigner[0][2][0]['value'], der_encoder(cn)) + + if extn['extnID'] == rfc8520.id_pe_mud_url: + mudurl, rest = der_decoder( + extn['extnValue'], rfc8520.MUDURLSyntax()) + + self.assertEqual(extn['extnValue'], der_encoder(mudurl)) + self.assertEqual(".json", mudurl[-5:]) + + self.assertIn(rfc8520.id_pe_mudsigner, extn_list) + self.assertIn(rfc8520.id_pe_mud_url, extn_list) + + def testExtensionsMap(self): + substrate = pem.readBase64fromText(self.mud_cert_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + for extn in asn1Object['tbsCertificate']['extensions']: + if extn['extnID'] in rfc5280.certificateExtensionsMap.keys(): + extnValue, rest = der_decoder( + extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + self.assertEqual(extn['extnValue'], der_encoder(extnValue)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc8619.py b/tests/test_rfc8619.py new file mode 100644 index 0000000..cd54db6 --- /dev/null +++ b/tests/test_rfc8619.py @@ -0,0 +1,80 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der import decoder as der_decoder +from pyasn1.codec.der import encoder as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc8619 + + +class HKDFSHA256TestCase(unittest.TestCase): + alg_id_1_pem_text = "MA0GCyqGSIb3DQEJEAMc" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + + substrate = pem.readBase64fromText(self.alg_id_1_pem_text) + asn1Object, rest = der_decoder.decode( + substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + + self.assertEqual( + rfc8619.id_alg_hkdf_with_sha256, asn1Object['algorithm']) + + +class HKDFSHA384TestCase(unittest.TestCase): + alg_id_1_pem_text = "MA0GCyqGSIb3DQEJEAMd" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + + substrate = pem.readBase64fromText(self.alg_id_1_pem_text) + asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + self.assertEqual( + rfc8619.id_alg_hkdf_with_sha384, asn1Object['algorithm']) + + +class HKDFSHA512TestCase(unittest.TestCase): + alg_id_1_pem_text = "MA0GCyqGSIb3DQEJEAMe" + + def setUp(self): + self.asn1Spec = rfc5280.AlgorithmIdentifier() + + def testDerCodec(self): + + substrate = pem.readBase64fromText(self.alg_id_1_pem_text) + + asn1Object, rest = der_decoder.decode( + substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder.encode(asn1Object)) + self.assertEqual( + rfc8619.id_alg_hkdf_with_sha512, asn1Object['algorithm']) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc8649.py b/tests/test_rfc8649.py new file mode 100644 index 0000000..67f8f9f --- /dev/null +++ b/tests/test_rfc8649.py @@ -0,0 +1,60 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc4055 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc8649 + + +class RootCertificateExtnTestCase(unittest.TestCase): + extn_pem_text = """\ +MGEGCisGAQQBg5IbAgEEUzBRMA0GCWCGSAFlAwQCAwUABEBxId+rK+WVDLOda2Yk +FFRbqQAztXhs91j/RxHjYJIv/3gleQg3Qix/yQy2rIg3xysjCvHWw8AuYOGVh/sL +GANG +""" + + def setUp(self): + self.asn1Spec = rfc5280.Extension() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.extn_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + self.assertEqual(rfc8649.id_ce_hashOfRootKey, asn1Object['extnID']) + + hashed_root_key, rest = der_decoder( + asn1Object['extnValue'], rfc8649.HashedRootKey()) + + self.assertFalse(rest) + self.assertTrue(hashed_root_key.prettyPrint()) + self.assertEqual(asn1Object['extnValue'], der_encoder(hashed_root_key)) + self.assertEqual( + rfc4055.id_sha512, hashed_root_key['hashAlg']['algorithm']) + + def testExtensionsMap(self): + substrate = pem.readBase64fromText(self.extn_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + + self.assertFalse(rest) + self.assertEqual(rfc8649.id_ce_hashOfRootKey, asn1Object['extnID']) + self.assertIn(asn1Object['extnID'], rfc5280.certificateExtensionsMap) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc8692.py b/tests/test_rfc8692.py new file mode 100644 index 0000000..416b59c --- /dev/null +++ b/tests/test_rfc8692.py @@ -0,0 +1,55 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2019, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5751 +from pyasn1_modules import rfc8692 + + +class AlgorithmIdentifierTestCase(unittest.TestCase): + pem_text = """\ +MEowCwYJYIZIAWUDBAILMAsGCWCGSAFlAwQCDDAKBggrBgEFBQcGHjAKBggrBgEF +BQcGHzAKBggrBgEFBQcGIDAKBggrBgEFBQcGIQ== +""" + + def setUp(self): + self.asn1Spec = rfc5751.SMIMECapabilities() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + oid_list = ( + rfc8692.id_shake128, + rfc8692.id_shake256, + rfc8692.id_RSASSA_PSS_SHAKE128, + rfc8692.id_RSASSA_PSS_SHAKE256, + rfc8692.id_ecdsa_with_shake128, + rfc8692.id_ecdsa_with_shake256, + ) + + count = 0 + for algid in asn1Object: + self.assertTrue(algid['capabilityID'] in oid_list) + count += 1 + + self.assertTrue(len(oid_list), count) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc8696.py b/tests/test_rfc8696.py new file mode 100644 index 0000000..119f658 --- /dev/null +++ b/tests/test_rfc8696.py @@ -0,0 +1,193 @@ +# +# 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 +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5083 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc8696 + + +class KeyTransPSKTestCase(unittest.TestCase): + key_trans_psk_pem_text = """\ +MIICigYLKoZIhvcNAQkQARegggJ5MIICdQIBADGCAiekggIjBgsqhkiG9w0BCRANATCCAhIC +AQAEE3B0Zi1rbWM6MTM2MTQxMjIxMTIwDQYLKoZIhvcNAQkQAx0wCwYJYIZIAWUDBAEtMIIB +sDCCAawCAQKAFJ7rZ8m5WnTUTS8WOWaA6AG1y6ScMA0GCSqGSIb3DQEBAQUABIIBgKo/Hkhu +eoOdn1/cIEpt38NbEEdSC586IWcG+0l+ND9pcmQvvKvscpvFFVAjqLjvoXGatmSazr2Q4BVS +yWKm0JqlyVWEAhRsU7wNlD7zRAKI8+obWpU57gjEKs13D8gb1PI2YPZWajN1Ye+yHSF6h+fb +7YtaQepxTGHYF0LgHaAC8cqtgwIRW8N4Gnvl0Uuz+YEZXUX0I8fvJG6MKCEFzwHvfrfPb3rW +B8k7BHfekRpY+793JNrjSP2lY+W0fhqBN8dALDKGqlbUCyojMQkQiD/iXSBRbZWiJ1CE92iT +x7Ji9irq8rhYDNoDP2vghJUaepoZgIJwPWqhoTH+KRPqHTjLnnbi/TGzEdeO5h0C9Gc0DVzs +9OHvHknQ7mSxPT9xKMXGztVT+P3a9ct6TaMotpMqL9cuZxTYGpHMYNkLSUXFSadAGFrgP7QV +FGwC/Z/YomEzSLPgZi8HnVHsAGkJzXxmM/PJBu4dAXcKjEv/GgpmaS2B7gKHUpTyyAgdsBsy +2AQo6glHJQ+mbNUlWV5Sppqq3ojvzxsPEIq+KRBgORsc31kH82tAZ+RTQjA3BgkqhkiG9w0B +BwEwGwYJYIZIAWUDBAEuMA4EDMr+ur76ztut3sr4iIANmvLRbyFUf87+2bPvLQQMoOWSXMGE +4BckY8RM +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.key_trans_psk_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual( + rfc5083.id_ct_authEnvelopedData, asn1Object['contentType']) + + aed, rest = der_decoder( + asn1Object['content'], + asn1Spec=rfc5083.AuthEnvelopedData()) + + self.assertFalse(rest) + self.assertTrue(aed.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(aed)) + self.assertEqual(0, aed['version']) + + ri = aed['recipientInfos'][0] + self.assertEqual(rfc8696.id_ori_keyTransPSK, ri['ori']['oriType']) + + ktpsk, rest = der_decoder( + ri['ori']['oriValue'], + asn1Spec=rfc8696.KeyTransPSKRecipientInfo()) + + self.assertFalse(rest) + self.assertTrue(ktpsk.prettyPrint()) + self.assertEqual(ri['ori']['oriValue'], der_encoder(ktpsk)) + self.assertEqual(0, ktpsk['version']) + + ktri = ktpsk['ktris'][0] + self.assertEqual(2, ktri['version']) + + def testOtherRecipientInfoMap(self): + substrate = pem.readBase64fromText(self.key_trans_psk_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual( + rfc5083.id_ct_authEnvelopedData, asn1Object['contentType']) + + aed, rest = der_decoder( + asn1Object['content'], + asn1Spec=rfc5083.AuthEnvelopedData()) + + self.assertFalse(rest) + self.assertTrue(aed.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(aed)) + self.assertEqual(0, aed['version']) + + ri = aed['recipientInfos'][0] + self.assertIn(ri['ori']['oriType'], rfc5652.otherRecipientInfoMap) + + ori, rest = der_decoder( + ri['ori']['oriValue'], + asn1Spec=rfc5652.otherRecipientInfoMap[ri['ori']['oriType']]) + + self.assertFalse(rest) + self.assertTrue(ori.prettyPrint()) + self.assertEqual(ri['ori']['oriValue'], der_encoder(ori)) + +class KeyAgreePSKTestCase(unittest.TestCase): + key_agree_psk_pem_text = """\ +MIIBRwYLKoZIhvcNAQkQARegggE2MIIBMgIBADGB5aSB4gYLKoZIhvcNAQkQDQIwgdICAQAE +FHB0Zi1rbWM6MjE2ODQwMTEwMTIxoFWhUzATBgYrgQQBCwEGCWCGSAFlAwQBLQM8AAQ5G0Em +Jk/2ks8sXY1kzbuG3Uu3ttWwQRXALFDJICjvYfr+yTpOQVkchm88FAh9MEkw4NKctokKNgps +MA0GCyqGSIb3DQEJEAMdMAsGCWCGSAFlAwQBLTBEMEKgFgQU6CGLmLi32Gtenr3IrrjE7NwF +xSkEKCKf4LReQAA+fYJE7Bt+f/ssjcoWw29XNyIlU6cSY6kr3giGamAtY/QwNwYJKoZIhvcN +AQcBMBsGCWCGSAFlAwQBLjAOBAzbrd7K+IjK/rq++s6ADfxtb4I+PtLSCdDG/88EDFUCYMQu +WylxlCbB/w== +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.key_agree_psk_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual( + rfc5083.id_ct_authEnvelopedData, asn1Object['contentType']) + + aed, rest = der_decoder( + asn1Object['content'], + asn1Spec=rfc5083.AuthEnvelopedData()) + + self.assertFalse(rest) + self.assertTrue(aed.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(aed)) + self.assertEqual(0, aed['version']) + + ri = aed['recipientInfos'][0] + self.assertEqual(rfc8696.id_ori_keyAgreePSK, ri['ori']['oriType']) + + kapsk, rest = der_decoder( + ri['ori']['oriValue'], + asn1Spec=rfc8696.KeyAgreePSKRecipientInfo()) + + self.assertFalse(rest) + self.assertTrue(kapsk.prettyPrint()) + self.assertEqual(ri['ori']['oriValue'], der_encoder(kapsk)) + self.assertEqual(0, kapsk['version']) + + rek = kapsk['recipientEncryptedKeys'][0] + ski = rek['rid']['rKeyId']['subjectKeyIdentifier'] + expected_ski = univ.OctetString( + hexValue='e8218b98b8b7d86b5e9ebdc8aeb8c4ecdc05c529') + + self.assertEqual(expected_ski, ski) + + def testOtherRecipientInfoMap(self): + substrate = pem.readBase64fromText(self.key_agree_psk_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual( + rfc5083.id_ct_authEnvelopedData, asn1Object['contentType']) + + aed, rest = der_decoder( + asn1Object['content'], + asn1Spec=rfc5083.AuthEnvelopedData()) + + self.assertFalse(rest) + self.assertTrue(aed.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(aed)) + self.assertEqual(0, aed['version']) + + ri = aed['recipientInfos'][0] + self.assertIn(ri['ori']['oriType'], rfc5652.otherRecipientInfoMap) + + ori, rest = der_decoder( + ri['ori']['oriValue'], + asn1Spec=rfc5652.otherRecipientInfoMap[ri['ori']['oriType']]) + + self.assertFalse(rest) + self.assertTrue(ori.prettyPrint()) + self.assertEqual(ri['ori']['oriValue'], der_encoder(ori)) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc8702.py b/tests/test_rfc8702.py new file mode 100644 index 0000000..d6303cf --- /dev/null +++ b/tests/test_rfc8702.py @@ -0,0 +1,140 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2020, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc2985 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc6211 +from pyasn1_modules import rfc8702 + + +class AlgorithmIdentifierTestCase(unittest.TestCase): + pem_text = """\ +MEowCwYJYIZIAWUDBAILMAsGCWCGSAFlAwQCDDAKBggrBgEFBQcGHjAKBggrBgEF +BQcGHzAKBggrBgEFBQcGIDAKBggrBgEFBQcGIQ== +""" + + def setUp(self): + self.asn1Spec = rfc2985.SMIMECapabilities() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + oid_list = ( + rfc8702.id_shake128, + rfc8702.id_shake256, + rfc8702.id_RSASSA_PSS_SHAKE128, + rfc8702.id_RSASSA_PSS_SHAKE256, + rfc8702.id_ecdsa_with_shake128, + rfc8702.id_ecdsa_with_shake256, + ) + + for algid in asn1Object: + self.assertIn(algid['algorithm'], oid_list) + + +class AuthenticatedDataTestCase(unittest.TestCase): + auth_message_pem_text = """\ +MIIDqgYLKoZIhvcNAQkQAQKgggOZMIIDlQIBADGCAk8wggJLAgEAMDMwJjEUMBIG +A1UECgwLZXhhbXBsZS5jb20xDjAMBgNVBAMMBUFsaWNlAgkAg/ULtwvVxA4wDQYJ +KoZIhvcNAQEBBQAEggIAdZphtN3x8a8kZoAFY15HYRD6JyPBueRUhLbTPoOH3pZ9 +xeDK+zVXGlahl1y1UOe+McEx2oD7cxAkhFuruNZMrCYEBCTZMwVhyEOZlBXdZEs8 +rZUHL3FFE5PJnygsSIO9DMxd1UuTFGTgCm5V5ZLFGmjeEGJRbsfTyo52S7iseJqI +N3dl743DbApu0+yuUoXKxqKdUFlEVxmhvc+Qbg/zfiwu8PTsYiUQDMBi4cdIlju8 +iLjj389xQHNyndXHWD51is89GG8vpBe+IsN8mnbGtCcpqtJ/c65ErJhHTR7rSJSM +EqQD0LPOCKIY1q9FaSSJfMXJZk9t/rPxgUEVjfw7hAkKpgOAqoZRN+FpnFyBl0Fn +nXo8kLp55tfVyNibtUpmdCPkOwt9b3jAtKtnvDQ2YqY1/llfEUnFOVDKwuC6MYwi +fm92qNlAQA/T0+ocjs6gA9zOLx+wD1zqM13hMD/L+T2OHL/WgvGb62JLrNHXuPWA +8RShO4kIlPtARKXap2S3+MX/kpSUUrNa65Y5uK1jwFFclczG+CPCIBBn6iJiQT/v +OX1I97YUP4Qq6OGkjK064Bq6o8+e5+NmIOBcygYRv6wA7vGkmPLSWbnw99qD728b +Bh84fC3EjItdusqGIwjzL0eSUWXJ5eu0Z3mYhJGN1pe0R/TEB5ibiJsMLpWAr3gw +FQYJYIZIAWUDBAITMAgEBnB5YXNuMaELBglghkgBZQMEAgswNQYJKoZIhvcNAQcB +oCgEJldhdHNvbiwgY29tZSBoZXJlIC0gSSB3YW50IHRvIHNlZSB5b3UuooG/MBgG +CSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE5MDkxOTEz +NDEwMFowHwYJKoZIhvcNAQkEMRIEENiFx45okcgTCVIBhhgF+ogwLwYLKoZIhvcN +AQkQAgQxIDAeDBFXYXRzb24sIGNvbWUgaGVyZQYJKoZIhvcNAQcBMDMGCSqGSIb3 +DQEJNDEmMCQwCwYJYIZIAWUDBAILohUGCWCGSAFlAwQCEzAIBAZweWFzbjEEIBxm +7hx+iivDlWYp8iUmYYbc2xkpBAcTACkWH+KBRZuF +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.auth_message_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual(rfc5652.id_ct_authData, asn1Object['contentType']) + ad, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.AuthenticatedData()) + + self.assertFalse(rest) + self.assertTrue(ad.prettyPrint()) + self.assertEqual(asn1Object['content'], der_encoder(ad)) + + self.assertEqual( + rfc8702.id_shake128, ad['digestAlgorithm']['algorithm']) + + ad_mac = ad['macAlgorithm'] + self.assertEqual( + rfc8702.id_KMACWithSHAKE128, ad_mac['algorithm']) + + kmac128_p, rest = der_decoder( + ad_mac['parameters'], + asn1Spec=rfc5280.algorithmIdentifierMap[ad_mac['algorithm']]) + + self.assertFalse(rest) + self.assertTrue(kmac128_p.prettyPrint()) + self.assertEqual(ad_mac['parameters'], der_encoder(kmac128_p)) + + self.assertEqual( + univ.OctetString("pyasn1"), kmac128_p['customizationString']) + + found_kmac128_params = False + for attr in ad['authAttrs']: + if attr['attrType'] == rfc6211.id_aa_cmsAlgorithmProtect: + av, rest = der_decoder( + attr['attrValues'][0], + asn1Spec=rfc6211.CMSAlgorithmProtection()) + + self.assertFalse(rest) + self.assertTrue(av.prettyPrint()) + self.assertEqual(attr['attrValues'][0], der_encoder(av)) + + self.assertEqual( + rfc8702.id_shake128, av['digestAlgorithm']['algorithm']) + + self.assertEqual( + rfc8702.id_KMACWithSHAKE128, av['macAlgorithm']['algorithm']) + + found_kmac128_params = True + + self.assertTrue(found_kmac128_params) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + import sys + + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tests/test_rfc8708.py b/tests/test_rfc8708.py new file mode 100644 index 0000000..049aead --- /dev/null +++ b/tests/test_rfc8708.py @@ -0,0 +1,127 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley +# Copyright (c) 2020, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# + +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc8708 + + +class HashSigPublicKeyTestCase(unittest.TestCase): + public_key_pem_text = """\ +MFAwDQYLKoZIhvcNAQkQAxEDPwAEPAAAAAIAAAAGAAAAA9CPq9SiCR/wqMtO2DTn +RTQypYiFzZugQxI1Rmv/llHGySEkQE1F+lPPFhwo8a1ajg== +""" + + def setUp(self): + self.asn1Spec = rfc5280.SubjectPublicKeyInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.public_key_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual( + asn1Object['algorithm']['algorithm'], + rfc8708.id_alg_hss_lms_hashsig) + + +class HashSigSignedDataTestCase(unittest.TestCase): + signed_data_pem_text = """\ +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 +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.signed_data_pem_text) + asn1Object, rest = der_decoder(substrate, asn1Spec=self.asn1Spec) + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + self.assertEqual(asn1Object['contentType'], rfc5652.id_signedData) + sd, rest = der_decoder( + asn1Object['content'], asn1Spec=rfc5652.SignedData()) + + oid = sd['signerInfos'][0]['signatureAlgorithm']['algorithm'] + self.assertEqual(rfc8708.id_alg_hss_lms_hashsig, oid) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_rfc8769.py b/tests/test_rfc8769.py new file mode 100644 index 0000000..614f326 --- /dev/null +++ b/tests/test_rfc8769.py @@ -0,0 +1,134 @@ +# +# This file is part of pyasn1-modules software. +# +# Copyright (c) 2020, Vigil Security, LLC +# License: http://snmplabs.com/pyasn1/license.html +# +import sys +import unittest + +from pyasn1.codec.der.decoder import decode as der_decoder +from pyasn1.codec.der.encoder import encode as der_encoder + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc8769 + + +class CBORContentTestCase(unittest.TestCase): + pem_text = """\ +MIIEHwYJKoZIhvcNAQcCoIIEEDCCBAwCAQMxDTALBglghkgBZQMEAgIwIQYLKoZIhvcNAQkQ +ASygEgQQgw9kUnVzc/tADzMzMzMzM6CCAnwwggJ4MIIB/qADAgECAgkApbNUKBuwbjswCgYI +KoZIzj0EAwMwPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMRAwDgYDVQQHDAdIZXJuZG9u +MREwDwYDVQQKDAhCb2d1cyBDQTAeFw0xOTA1MjkxNDQ1NDFaFw0yMDA1MjgxNDQ1NDFaMHAx +CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJWQTEQMA4GA1UEBxMHSGVybmRvbjEQMA4GA1UEChMH +RXhhbXBsZTEOMAwGA1UEAxMFQWxpY2UxIDAeBgkqhkiG9w0BCQEWEWFsaWNlQGV4YW1wbGUu +Y29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE+M2fBy/sRA6V1pKFqecRTE8+LuAHtZxes1wm +JZrBBg+bz7uYZfYQxI3dVB0YCSD6Mt3yXFlnmfBRwoqyArbjIBYrDbHBv2k8Csg2DhQ7qs/w +to8hMKoFgkcscqIbiV7Zo4GUMIGRMAsGA1UdDwQEAwIHgDBCBglghkgBhvhCAQ0ENRYzVGhp +cyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUgdHJ1c3RlZCBmb3IgYW55IHB1cnBvc2UuMB0GA1Ud +DgQWBBTEuloOPnrjPIGw9AKqaLsW4JYONTAfBgNVHSMEGDAWgBTyNds0BNqlVfK9aQOZsGLs +4hUIwTAKBggqhkjOPQQDAwNoADBlAjBjuR/RNbgL3kRhmn+PJTeKaL9sh/oQgHOYTgLmSnv3 ++NDCkhfKuMNoo/tHrkmihYgCMQC94MaerDIrQpi0IDh+v0QSAv9rMife8tClafXWtDwwL8MS +7oAh0ymT446Uizxx3PUxggFTMIIBTwIBATBMMD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJW +QTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0ECCQCls1QoG7BuOzALBglg +hkgBZQMEAgKgezAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQASwwHAYJKoZIhvcNAQkFMQ8X +DTIwMDExNDIyMjIxNVowPwYJKoZIhvcNAQkEMTIEMADSWdHn4vsesm9XnjJq1WxkoV6EtD+f +qDAs1JEpZMZ+n8AtUxvC5SFobYpGCl+fsDAKBggqhkjOPQQDAwRmMGQCMGclPwvZLwVJqgON +mOfnxSF8Cqn3AC+ZFBg7VplspiuhKPNIyu3IofqZjCxw0TzSpAIwEK0JxNlY28KDb5te0iN6 +I2hw+am26W+PRyltVVGUAISHM2kA4tG39HcxEQi+6HJx +""" + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + + layers = { } + layers.update(rfc5652.cmsContentTypesMap) + + getNextLayer = { + rfc5652.id_ct_contentInfo: lambda x: x['contentType'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContentType'], + } + + getNextSubstrate = { + rfc5652.id_ct_contentInfo: lambda x: x['content'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContent'], + } + + next_layer = rfc5652.id_ct_contentInfo + while next_layer in layers: + asn1Object, rest = der_decoder( + substrate, asn1Spec=layers[next_layer]) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + substrate = getNextSubstrate[next_layer](asn1Object) + next_layer = getNextLayer[next_layer](asn1Object) + + self.assertEqual(rfc8769.id_ct_cbor, next_layer) + + +class CBORSequenceContentTestCase(unittest.TestCase): + pem_text = """\ +MIIEKQYJKoZIhvcNAQcCoIIEGjCCBBYCAQMxDTALBglghkgBZQMEAgIwKgYLKoZIhvcNAQkQ +AS2gGwQZgw9kUnVzc/tADzMzMzMzM6MDCSD1YWFhYqCCAnwwggJ4MIIB/qADAgECAgkApbNU +KBuwbjswCgYIKoZIzj0EAwMwPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMRAwDgYDVQQH +DAdIZXJuZG9uMREwDwYDVQQKDAhCb2d1cyBDQTAeFw0xOTA1MjkxNDQ1NDFaFw0yMDA1Mjgx +NDQ1NDFaMHAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJWQTEQMA4GA1UEBxMHSGVybmRvbjEQ +MA4GA1UEChMHRXhhbXBsZTEOMAwGA1UEAxMFQWxpY2UxIDAeBgkqhkiG9w0BCQEWEWFsaWNl +QGV4YW1wbGUuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE+M2fBy/sRA6V1pKFqecRTE8+ +LuAHtZxes1wmJZrBBg+bz7uYZfYQxI3dVB0YCSD6Mt3yXFlnmfBRwoqyArbjIBYrDbHBv2k8 +Csg2DhQ7qs/wto8hMKoFgkcscqIbiV7Zo4GUMIGRMAsGA1UdDwQEAwIHgDBCBglghkgBhvhC +AQ0ENRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUgdHJ1c3RlZCBmb3IgYW55IHB1cnBv +c2UuMB0GA1UdDgQWBBTEuloOPnrjPIGw9AKqaLsW4JYONTAfBgNVHSMEGDAWgBTyNds0BNql +VfK9aQOZsGLs4hUIwTAKBggqhkjOPQQDAwNoADBlAjBjuR/RNbgL3kRhmn+PJTeKaL9sh/oQ +gHOYTgLmSnv3+NDCkhfKuMNoo/tHrkmihYgCMQC94MaerDIrQpi0IDh+v0QSAv9rMife8tCl +afXWtDwwL8MS7oAh0ymT446Uizxx3PUxggFUMIIBUAIBATBMMD8xCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9ndXMgQ0ECCQCls1Qo +G7BuOzALBglghkgBZQMEAgKgezAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAS0wHAYJKoZI +hvcNAQkFMQ8XDTIwMDExNDIyMjIxNVowPwYJKoZIhvcNAQkEMTIEMOsEu3dGU5j6fKZbsZPL +LDA8QWxpP36CPDZWr3BVJ3R5mMCKCSmoWtVRnB7XASQcjTAKBggqhkjOPQQDAwRnMGUCMBLW +PyYw4c11nrH97KHnEmx3BSDX/SfepFNM6PoPR5HCI+OR/v/wlIIByuhyrIl8xAIxAK8dEwOe +I06um+ATKQzUcbgq0PCKA7T31pAq46fsWc5tA+mMARTrxZjSXsDneeAWpw== +""" + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.pem_text) + + layers = { } + layers.update(rfc5652.cmsContentTypesMap) + + getNextLayer = { + rfc5652.id_ct_contentInfo: lambda x: x['contentType'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContentType'], + } + + getNextSubstrate = { + rfc5652.id_ct_contentInfo: lambda x: x['content'], + rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContent'], + } + + next_layer = rfc5652.id_ct_contentInfo + while next_layer in layers: + asn1Object, rest = der_decoder( + substrate, asn1Spec=layers[next_layer]) + + self.assertFalse(rest) + self.assertTrue(asn1Object.prettyPrint()) + self.assertEqual(substrate, der_encoder(asn1Object)) + + substrate = getNextSubstrate[next_layer](asn1Object) + next_layer = getNextLayer[next_layer](asn1Object) + + self.assertEqual(rfc8769.id_ct_cborSequence, next_layer) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + import sys + + result = unittest.TextTestRunner(verbosity=2).run(suite) + sys.exit(not result.wasSuccessful()) diff --git a/tools/cmpdump.py b/tools/cmpdump.py index ee8092b..ebf8dba 100755 --- a/tools/cmpdump.py +++ b/tools/cmpdump.py @@ -2,8 +2,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Read ASN.1/PEM CMP message on stdin, parse into # plain text, then build substrate from it diff --git a/tools/crldump.py b/tools/crldump.py index 9731129..9eaf6ba 100755 --- a/tools/crldump.py +++ b/tools/crldump.py @@ -2,8 +2,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Read X.509 CRL on stdin, print them pretty and encode back into # original wire format. diff --git a/tools/crmfdump.py b/tools/crmfdump.py index 854bfec..f23fd0d 100755 --- a/tools/crmfdump.py +++ b/tools/crmfdump.py @@ -2,8 +2,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Read ASN.1/PEM X.509 CRMF request on stdin, parse into # plain text, then build substrate from it diff --git a/tools/ocspclient.py b/tools/ocspclient.py index 2827604..84f06fb 100755 --- a/tools/ocspclient.py +++ b/tools/ocspclient.py @@ -2,8 +2,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # import hashlib import sys diff --git a/tools/ocspreqdump.py b/tools/ocspreqdump.py index f613f3a..3e43418 100755 --- a/tools/ocspreqdump.py +++ b/tools/ocspreqdump.py @@ -2,8 +2,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Read ASN.1/PEM X.509 CRMF request on stdin, parse into # plain text, then build substrate from it diff --git a/tools/ocsprspdump.py b/tools/ocsprspdump.py index 3535795..1f79acd 100755 --- a/tools/ocsprspdump.py +++ b/tools/ocsprspdump.py @@ -2,8 +2,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Read ASN.1/PEM OCSP response on stdin, parse into # plain text, then build substrate from it diff --git a/tools/pkcs10dump.py b/tools/pkcs10dump.py index e8c6da5..385312a 100755 --- a/tools/pkcs10dump.py +++ b/tools/pkcs10dump.py @@ -2,8 +2,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Read ASN.1/PEM X.509 certificate requests (PKCS#10 format) on stdin, # parse each into plain text, then build substrate from it diff --git a/tools/pkcs1dump.py b/tools/pkcs1dump.py index 520fc4c..72fb1dd 100755 --- a/tools/pkcs1dump.py +++ b/tools/pkcs1dump.py @@ -2,8 +2,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Read unencrypted PKCS#1/PKIX-compliant, PEM&DER encoded private keys on # stdin, print them pretty and encode back into original wire format. diff --git a/tools/pkcs7dump.py b/tools/pkcs7dump.py index c01e19c..7ac2eb9 100755 --- a/tools/pkcs7dump.py +++ b/tools/pkcs7dump.py @@ -2,8 +2,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Read ASN.1/PEM PKCS#7 on stdin, parse it into plain text, # then build substrate from it diff --git a/tools/pkcs8dump.py b/tools/pkcs8dump.py index d645a87..e95a549 100755 --- a/tools/pkcs8dump.py +++ b/tools/pkcs8dump.py @@ -2,8 +2,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Read bunch of ASN.1/PEM plain/encrypted private keys in PKCS#8 # format on stdin, parse each into plain text, then build substrate from it diff --git a/tools/snmpget.py b/tools/snmpget.py index 877d521..c6d97a5 100755 --- a/tools/snmpget.py +++ b/tools/snmpget.py @@ -2,8 +2,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Generate SNMPGET request, parse response # diff --git a/tools/x509dump-rfc5280.py b/tools/x509dump-rfc5280.py index d1ae38b..26a79e9 100755 --- a/tools/x509dump-rfc5280.py +++ b/tools/x509dump-rfc5280.py @@ -4,8 +4,8 @@ # This file is part of pyasn1-modules software. # # Created by Stanisław Pitucha with asn1ate tool. -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Read ASN.1/PEM X.509 certificates on stdin, parse each into plain text, # then build substrate from it (using RFC5280) diff --git a/tools/x509dump.py b/tools/x509dump.py index 5a36915..1b8cca4 100755 --- a/tools/x509dump.py +++ b/tools/x509dump.py @@ -2,8 +2,8 @@ # # This file is part of pyasn1-modules software. # -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html +# Copyright (c) 2005-2020, Ilya Etingof +# License: http://snmplabs.com/pyasn1/license.html # # Read ASN.1/PEM X.509 certificates on stdin, parse each into plain text, # then build substrate from it diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..ee8971d --- /dev/null +++ b/tox.ini @@ -0,0 +1,49 @@ +[tox] +minversion = 3.5.0 +envlist = + py{38, 39, 310, 311, 312, 313, py38, py39} + cover, bandit, build +isolated_build = true +skip_missing_interpreters = true + +[testenv] +commands = + {envpython} -m unittest discover -s tests +deps = + pyasn1>=0.4.6,<0.7.0 + +[testenv:cover] +basepython = python3 +deps = + coverage +commands = coverage erase + coverage run --source pyasn1_modules -m unittest discover {posargs} + coverage report --fail-under 93 + +[testenv:bandit] +skip_install = true +deps = + bandit +commands = + bandit -r pyasn1 -c .bandit.yml + +[testenv:build] +skip_install = true +deps = + build + twine +commands = + {envpython} -m build + {envpython} -m twine check --strict dist/pyasn1_modules*.whl + {envpython} -m twine check --strict dist/pyasn1_modules*.tar.gz + +[gh-actions] +python = + 3.8: py38 + 3.9: py39 + 3.10: py310, cover, build, bandit + 3.11: py311 + 3.12: py312 + 3.13: py313 + pypy-3.8: pypy38 + pypy-3.9: pypy39