aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Housley <housley@vigilsec.com>2019-06-15 11:32:49 -0400
committerIlya Etingof <etingof@gmail.com>2019-06-15 17:32:49 +0200
commitfc113ede3a2db3a2fd3932e83295adcd8f158493 (patch)
treeff54dd1b5f2c6c932c5efe6d8d69527aed0580e2
parent1de1622ed5751168b090e9aa3d78cec83d13f3fe (diff)
downloadpyasn1-modules-fc113ede3a2db3a2fd3932e83295adcd8f158493.tar.gz
Add support for RFC 7191 (#44)
-rw-r--r--CHANGES.txt2
-rw-r--r--pyasn1_modules/rfc7191.py234
-rw-r--r--tests/__main__.py1
-rwxr-xr-xtests/test_rfc7191.py201
4 files changed, 438 insertions, 0 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 3a7b723..03c1ba4 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -20,6 +20,8 @@ Revision 0.2.6, released XX-05-2019
- 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
Revision 0.2.5, released 24-04-2019
-----------------------------------
diff --git a/pyasn1_modules/rfc7191.py b/pyasn1_modules/rfc7191.py
new file mode 100644
index 0000000..d3e2f85
--- /dev/null
+++ b/pyasn1_modules/rfc7191.py
@@ -0,0 +1,234 @@
+# This file is being contributed to of pyasn1-modules software.
+#
+# Created by Russ Housley without assistance from the asn1ate tool.
+# Copyright (c) 2018, 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 tag
+from pyasn1.type import univ
+
+from pyasn1_modules import rfc5280
+
+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())
+)
+
+
+# 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.subtypeSpec=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())
+)
diff --git a/tests/__main__.py b/tests/__main__.py
index 101a2b2..879981e 100644
--- a/tests/__main__.py
+++ b/tests/__main__.py
@@ -40,6 +40,7 @@ suite = unittest.TestLoader().loadTestsFromNames(
'tests.test_rfc5940.suite',
'tests.test_rfc5958.suite',
'tests.test_rfc6019.suite',
+ 'tests.test_rfc7191.suite',
'tests.test_rfc7296.suite',
'tests.test_rfc8103.suite',
'tests.test_rfc8226.suite',
diff --git a/tests/test_rfc7191.py b/tests/test_rfc7191.py
new file mode 100755
index 0000000..664ead7
--- /dev/null
+++ b/tests/test_rfc7191.py
@@ -0,0 +1,201 @@
+#
+# This file is part of pyasn1-modules software.
+#
+# Created by Russ Housley
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+
+import sys
+
+from pyasn1.codec.der.decoder import decode as der_decode
+from pyasn1.codec.der.encoder import encode as der_encode
+
+from pyasn1_modules import pem
+from pyasn1_modules import rfc5652
+from pyasn1_modules import rfc7191
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+
+
+class ReceiptRequestTestCase(unittest.TestCase):
+ message1_pem_text = """\
+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
+"""
+
+ def setUp(self):
+ self.asn1Spec = rfc5652.ContentInfo()
+
+ def testDerCodec(self):
+ substrate = pem.readBase64fromText(self.message1_pem_text)
+ asn1Object, rest = der_decode (substrate, asn1Spec=self.asn1Spec)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert der_encode(asn1Object) == substrate
+
+ assert asn1Object['contentType'] == rfc5652.id_signedData
+ sd, rest = der_decode (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_decode(sav0,
+ asn1Spec=rfc7191.KeyPkgIdentifierAndReceiptReq())
+ assert not rest
+ assert sav.prettyPrint()
+ assert der_encode(sav) == sav0
+
+
+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_decode (substrate, asn1Spec=self.asn1Spec)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert der_encode(asn1Object) == substrate
+
+ assert asn1Object['contentType'] == rfc5652.id_signedData
+ sd, rest = der_decode (asn1Object['content'],
+ asn1Spec=rfc5652.SignedData())
+ assert not rest
+ assert sd.prettyPrint()
+ assert der_encode(sd) == asn1Object['content']
+
+ oid = sd['encapContentInfo']['eContentType']
+ assert oid == rfc7191.id_ct_KP_keyPackageReceipt
+ receipt, rest = der_decode(sd['encapContentInfo']['eContent'],
+ asn1Spec=rfc7191.KeyPackageReceipt())
+ assert not rest
+ assert receipt.prettyPrint()
+ assert der_encode(receipt) == sd['encapContentInfo']['eContent']
+
+ package_id_pem_text = "J7icVjsWIlGdF4cceb+siG3f+D0="
+ package_id = pem.readBase64fromText(package_id_pem_text)
+ assert receipt['receiptOf']['pkgID'] == package_id
+
+
+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_decode (substrate, asn1Spec=self.asn1Spec)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert der_encode(asn1Object) == substrate
+
+ assert asn1Object['contentType'] == rfc5652.id_signedData
+ sd, rest = der_decode (asn1Object['content'],
+ asn1Spec=rfc5652.SignedData())
+ assert not rest
+ assert sd.prettyPrint()
+ assert der_encode(sd) == asn1Object['content']
+
+ oid = sd['encapContentInfo']['eContentType']
+ assert oid == rfc7191.id_ct_KP_keyPackageError
+ kpe, rest = der_decode(sd['encapContentInfo']['eContent'],
+ asn1Spec=rfc7191.KeyPackageError())
+ assert not rest
+ assert kpe.prettyPrint()
+ assert der_encode(kpe) == sd['encapContentInfo']['eContent']
+
+ package_id_pem_text = "J7icVjsWIlGdF4cceb+siG3f+D0="
+ package_id = pem.readBase64fromText(package_id_pem_text)
+ assert kpe['errorOf']['pkgID'] == package_id
+ assert kpe['errorCode'] == rfc7191.EnumeratedErrorCode(value=10)
+
+
+suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
+
+if __name__ == '__main__':
+ unittest.TextTestRunner(verbosity=2).run(suite)