diff options
author | Russ Housley <housley@vigilsec.com> | 2019-04-22 14:45:52 -0400 |
---|---|---|
committer | Ilya Etingof <etingof@gmail.com> | 2019-04-22 20:45:52 +0200 |
commit | 67c96e9e8fa29f2cd7fbf073c124dc095ee9734f (patch) | |
tree | d9faad8cc5c29e5cde40d875bacb30cb9b963ee2 | |
parent | a4c0cf780dbd1b1065b012c95daa1a3913afab92 (diff) | |
download | pyasn1-modules-67c96e9e8fa29f2cd7fbf073c124dc095ee9734f.tar.gz |
Add RFC4108 (#25)
Add CMS Firmware Wrapper (RFC4108)
-rw-r--r-- | pyasn1_modules/rfc4108.py | 294 | ||||
-rw-r--r-- | tests/test_rfc4108.py | 80 |
2 files changed, 374 insertions, 0 deletions
diff --git a/pyasn1_modules/rfc4108.py b/pyasn1_modules/rfc4108.py new file mode 100644 index 0000000..9a7f190 --- /dev/null +++ b/pyasn1_modules/rfc4108.py @@ -0,0 +1,294 @@ +# +# 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 Firmware Wrapper +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc4108.txt +# + + +from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful + +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 Identifiers + +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 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()) +) diff --git a/tests/test_rfc4108.py b/tests/test_rfc4108.py new file mode 100644 index 0000000..49514b1 --- /dev/null +++ b/tests/test_rfc4108.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 + +from pyasn1.codec.der.decoder import decode as der_decode +from pyasn1.codec.der.encoder import encode as der_encode + +from pyasn1.type import univ + +from pyasn1_modules import pem +from pyasn1_modules import rfc5652 +from pyasn1_modules import rfc4108 + +try: + import unittest2 as unittest +except ImportError: + import unittest + + +class CMSFirmwareWrapperTestCase(unittest.TestCase): + pem_text = """\ +MIIEdwYJKoZIhvcNAQcCoIIEaDCCBGQCAQExDTALBglghkgBZQMEAgEwggIVBgsq +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 +EesxggI1MIICMQIBA4AUnutnybladNRNLxY5ZoDoAbXLpJwwCwYJYIZIAWUDBAIB +oHgwGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEQMCkGCyqGSIb3DQEJEAIkMRoG +CysGAQQBjb9BAQEqBgsrBgEEAY2/QQEBMDAvBgkqhkiG9w0BCQQxIgQgAJfvuasB +4P6WDLOkOyvj33YPgZW4olHbidzyh1EKP9YwCwYJKoZIhvcNAQELBIIBgDn0y+4B +cCX7ICovWcyWf0IxNXx7+1VlYneAZ8pMBaKu+6q7jRFZ+QsQFFbQ1yPO/3Pr2wVb +UJSJAL4QCJDurJ42LdPQIOGIV2aWq70vl6B9yt6svEdjxJ3XkopwcCBXLcB1Hp9b +6wYZzSFCujOlsABJiz2gMD6wUT4lq7RJO31LEPxx/Va4Ftp1F4okmgL8VpMemihU +atRXpIhedfli+TWEtMmoxcX3paLcU7MmJFUAwkHmb8rSRF5VBy5QWcNgzzskof0W +mCR/8bZjqR/g3VlFPyz7zOCxG/wIdZVAb4O/QP8fC0GhyHNE+NX6d+GI8RPpRyMf +5RfCCsHwbApCv8+tpFslYzwvUTIFx0y9zVrnkz/UrDjZtrKxLC0oRJlnlnKR1unm +lbolB9c2p60/mZHwQhLM5CjeYcMX3mMVJo4jqag+8o48CibW50h8y21usKaeA9b0 +9EMxfG3KaaP5mMEOZMpeGdUKQSJYweDstxlrY5ajPbeOycdMv7tRNoLpyw== +""" + + def setUp(self): + self.asn1Spec = rfc5652.ContentInfo() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.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 + inner, rest = der_decode(asn1Object['content'], asn1Spec=rfc5652.SignedData()) + + assert inner['encapContentInfo']['eContentType'] == rfc4108.id_ct_firmwarePackage + assert inner['encapContentInfo']['eContent'] + + found_target_hardware_identifier_attribute = False + for attr in inner['signerInfos'][0]['signedAttrs']: + if attr['attrType'] == rfc4108.id_aa_targetHardwareIDs: + found_target_hardware_identifier_attribute = True + assert found_target_hardware_identifier_attribute + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) |