• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# coding: utf-8
2
3"""
4ASN.1 type classes for cryptographic message syntax (CMS). Structures are also
5compatible with PKCS#7. Exports the following items:
6
7 - AuthenticatedData()
8 - AuthEnvelopedData()
9 - CompressedData()
10 - ContentInfo()
11 - DigestedData()
12 - EncryptedData()
13 - EnvelopedData()
14 - SignedAndEnvelopedData()
15 - SignedData()
16
17Other type classes are defined that help compose the types listed above.
18
19Most CMS structures in the wild are formatted as ContentInfo encapsulating one of the other types.
20"""
21
22from __future__ import unicode_literals, division, absolute_import, print_function
23
24try:
25    import zlib
26except (ImportError):
27    zlib = None
28
29from .algos import (
30    _ForceNullParameters,
31    DigestAlgorithm,
32    EncryptionAlgorithm,
33    EncryptionAlgorithmId,
34    HmacAlgorithm,
35    KdfAlgorithm,
36    RSAESOAEPParams,
37    SignedDigestAlgorithm,
38)
39from .core import (
40    Any,
41    BitString,
42    Choice,
43    Enumerated,
44    GeneralizedTime,
45    Integer,
46    ObjectIdentifier,
47    OctetBitString,
48    OctetString,
49    ParsableOctetString,
50    Sequence,
51    SequenceOf,
52    SetOf,
53    UTCTime,
54    UTF8String,
55)
56from .crl import CertificateList
57from .keys import PublicKeyInfo
58from .ocsp import OCSPResponse
59from .x509 import Attributes, Certificate, Extensions, GeneralName, GeneralNames, Name
60
61
62# These structures are taken from
63# ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-6.asc
64
65class ExtendedCertificateInfo(Sequence):
66    _fields = [
67        ('version', Integer),
68        ('certificate', Certificate),
69        ('attributes', Attributes),
70    ]
71
72
73class ExtendedCertificate(Sequence):
74    _fields = [
75        ('extended_certificate_info', ExtendedCertificateInfo),
76        ('signature_algorithm', SignedDigestAlgorithm),
77        ('signature', OctetBitString),
78    ]
79
80
81# These structures are taken from https://tools.ietf.org/html/rfc5652,
82# https://tools.ietf.org/html/rfc5083, http://tools.ietf.org/html/rfc2315,
83# https://tools.ietf.org/html/rfc5940, https://tools.ietf.org/html/rfc3274,
84# https://tools.ietf.org/html/rfc3281
85
86
87class CMSVersion(Integer):
88    _map = {
89        0: 'v0',
90        1: 'v1',
91        2: 'v2',
92        3: 'v3',
93        4: 'v4',
94        5: 'v5',
95    }
96
97
98class CMSAttributeType(ObjectIdentifier):
99    _map = {
100        '1.2.840.113549.1.9.3': 'content_type',
101        '1.2.840.113549.1.9.4': 'message_digest',
102        '1.2.840.113549.1.9.5': 'signing_time',
103        '1.2.840.113549.1.9.6': 'counter_signature',
104        # https://datatracker.ietf.org/doc/html/rfc2633#section-2.5.2
105        '1.2.840.113549.1.9.15': 'smime_capabilities',
106        # https://tools.ietf.org/html/rfc2633#page-26
107        '1.2.840.113549.1.9.16.2.11': 'encrypt_key_pref',
108        # https://tools.ietf.org/html/rfc3161#page-20
109        '1.2.840.113549.1.9.16.2.14': 'signature_time_stamp_token',
110        # https://tools.ietf.org/html/rfc6211#page-5
111        '1.2.840.113549.1.9.52': 'cms_algorithm_protection',
112        # https://docs.microsoft.com/en-us/previous-versions/hh968145(v%3Dvs.85)
113        '1.3.6.1.4.1.311.2.4.1': 'microsoft_nested_signature',
114        # Some places refer to this as SPC_RFC3161_OBJID, others szOID_RFC3161_counterSign.
115        # https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-crypt_algorithm_identifier
116        # refers to szOID_RFC3161_counterSign as "1.2.840.113549.1.9.16.1.4",
117        # but that OID is also called szOID_TIMESTAMP_TOKEN. Because of there being
118        # no canonical source for this OID, we give it our own name
119        '1.3.6.1.4.1.311.3.3.1': 'microsoft_time_stamp_token',
120    }
121
122
123class Time(Choice):
124    _alternatives = [
125        ('utc_time', UTCTime),
126        ('generalized_time', GeneralizedTime),
127    ]
128
129
130class ContentType(ObjectIdentifier):
131    _map = {
132        '1.2.840.113549.1.7.1': 'data',
133        '1.2.840.113549.1.7.2': 'signed_data',
134        '1.2.840.113549.1.7.3': 'enveloped_data',
135        '1.2.840.113549.1.7.4': 'signed_and_enveloped_data',
136        '1.2.840.113549.1.7.5': 'digested_data',
137        '1.2.840.113549.1.7.6': 'encrypted_data',
138        '1.2.840.113549.1.9.16.1.2': 'authenticated_data',
139        '1.2.840.113549.1.9.16.1.9': 'compressed_data',
140        '1.2.840.113549.1.9.16.1.23': 'authenticated_enveloped_data',
141    }
142
143
144class CMSAlgorithmProtection(Sequence):
145    _fields = [
146        ('digest_algorithm', DigestAlgorithm),
147        ('signature_algorithm', SignedDigestAlgorithm, {'implicit': 1, 'optional': True}),
148        ('mac_algorithm', HmacAlgorithm, {'implicit': 2, 'optional': True}),
149    ]
150
151
152class SetOfContentType(SetOf):
153    _child_spec = ContentType
154
155
156class SetOfOctetString(SetOf):
157    _child_spec = OctetString
158
159
160class SetOfTime(SetOf):
161    _child_spec = Time
162
163
164class SetOfAny(SetOf):
165    _child_spec = Any
166
167
168class SetOfCMSAlgorithmProtection(SetOf):
169    _child_spec = CMSAlgorithmProtection
170
171
172class CMSAttribute(Sequence):
173    _fields = [
174        ('type', CMSAttributeType),
175        ('values', None),
176    ]
177
178    _oid_specs = {}
179
180    def _values_spec(self):
181        return self._oid_specs.get(self['type'].native, SetOfAny)
182
183    _spec_callbacks = {
184        'values': _values_spec
185    }
186
187
188class CMSAttributes(SetOf):
189    _child_spec = CMSAttribute
190
191
192class IssuerSerial(Sequence):
193    _fields = [
194        ('issuer', GeneralNames),
195        ('serial', Integer),
196        ('issuer_uid', OctetBitString, {'optional': True}),
197    ]
198
199
200class AttCertVersion(Integer):
201    _map = {
202        0: 'v1',
203        1: 'v2',
204    }
205
206
207class AttCertSubject(Choice):
208    _alternatives = [
209        ('base_certificate_id', IssuerSerial, {'explicit': 0}),
210        ('subject_name', GeneralNames, {'explicit': 1}),
211    ]
212
213
214class AttCertValidityPeriod(Sequence):
215    _fields = [
216        ('not_before_time', GeneralizedTime),
217        ('not_after_time', GeneralizedTime),
218    ]
219
220
221class AttributeCertificateInfoV1(Sequence):
222    _fields = [
223        ('version', AttCertVersion, {'default': 'v1'}),
224        ('subject', AttCertSubject),
225        ('issuer', GeneralNames),
226        ('signature', SignedDigestAlgorithm),
227        ('serial_number', Integer),
228        ('att_cert_validity_period', AttCertValidityPeriod),
229        ('attributes', Attributes),
230        ('issuer_unique_id', OctetBitString, {'optional': True}),
231        ('extensions', Extensions, {'optional': True}),
232    ]
233
234
235class AttributeCertificateV1(Sequence):
236    _fields = [
237        ('ac_info', AttributeCertificateInfoV1),
238        ('signature_algorithm', SignedDigestAlgorithm),
239        ('signature', OctetBitString),
240    ]
241
242
243class DigestedObjectType(Enumerated):
244    _map = {
245        0: 'public_key',
246        1: 'public_key_cert',
247        2: 'other_objy_types',
248    }
249
250
251class ObjectDigestInfo(Sequence):
252    _fields = [
253        ('digested_object_type', DigestedObjectType),
254        ('other_object_type_id', ObjectIdentifier, {'optional': True}),
255        ('digest_algorithm', DigestAlgorithm),
256        ('object_digest', OctetBitString),
257    ]
258
259
260class Holder(Sequence):
261    _fields = [
262        ('base_certificate_id', IssuerSerial, {'implicit': 0, 'optional': True}),
263        ('entity_name', GeneralNames, {'implicit': 1, 'optional': True}),
264        ('object_digest_info', ObjectDigestInfo, {'implicit': 2, 'optional': True}),
265    ]
266
267
268class V2Form(Sequence):
269    _fields = [
270        ('issuer_name', GeneralNames, {'optional': True}),
271        ('base_certificate_id', IssuerSerial, {'explicit': 0, 'optional': True}),
272        ('object_digest_info', ObjectDigestInfo, {'explicit': 1, 'optional': True}),
273    ]
274
275
276class AttCertIssuer(Choice):
277    _alternatives = [
278        ('v1_form', GeneralNames),
279        ('v2_form', V2Form, {'implicit': 0}),
280    ]
281
282
283class IetfAttrValue(Choice):
284    _alternatives = [
285        ('octets', OctetString),
286        ('oid', ObjectIdentifier),
287        ('string', UTF8String),
288    ]
289
290
291class IetfAttrValues(SequenceOf):
292    _child_spec = IetfAttrValue
293
294
295class IetfAttrSyntax(Sequence):
296    _fields = [
297        ('policy_authority', GeneralNames, {'implicit': 0, 'optional': True}),
298        ('values', IetfAttrValues),
299    ]
300
301
302class SetOfIetfAttrSyntax(SetOf):
303    _child_spec = IetfAttrSyntax
304
305
306class SvceAuthInfo(Sequence):
307    _fields = [
308        ('service', GeneralName),
309        ('ident', GeneralName),
310        ('auth_info', OctetString, {'optional': True}),
311    ]
312
313
314class SetOfSvceAuthInfo(SetOf):
315    _child_spec = SvceAuthInfo
316
317
318class RoleSyntax(Sequence):
319    _fields = [
320        ('role_authority', GeneralNames, {'implicit': 0, 'optional': True}),
321        ('role_name', GeneralName, {'explicit': 1}),
322    ]
323
324
325class SetOfRoleSyntax(SetOf):
326    _child_spec = RoleSyntax
327
328
329class ClassList(BitString):
330    _map = {
331        0: 'unmarked',
332        1: 'unclassified',
333        2: 'restricted',
334        3: 'confidential',
335        4: 'secret',
336        5: 'top_secret',
337    }
338
339
340class SecurityCategory(Sequence):
341    _fields = [
342        ('type', ObjectIdentifier, {'implicit': 0}),
343        ('value', Any, {'explicit': 1}),
344    ]
345
346
347class SetOfSecurityCategory(SetOf):
348    _child_spec = SecurityCategory
349
350
351class Clearance(Sequence):
352    _fields = [
353        ('policy_id', ObjectIdentifier),
354        ('class_list', ClassList, {'default': set(['unclassified'])}),
355        ('security_categories', SetOfSecurityCategory, {'optional': True}),
356    ]
357
358
359class SetOfClearance(SetOf):
360    _child_spec = Clearance
361
362
363class BigTime(Sequence):
364    _fields = [
365        ('major', Integer),
366        ('fractional_seconds', Integer),
367        ('sign', Integer, {'optional': True}),
368    ]
369
370
371class LeapData(Sequence):
372    _fields = [
373        ('leap_time', BigTime),
374        ('action', Integer),
375    ]
376
377
378class SetOfLeapData(SetOf):
379    _child_spec = LeapData
380
381
382class TimingMetrics(Sequence):
383    _fields = [
384        ('ntp_time', BigTime),
385        ('offset', BigTime),
386        ('delay', BigTime),
387        ('expiration', BigTime),
388        ('leap_event', SetOfLeapData, {'optional': True}),
389    ]
390
391
392class SetOfTimingMetrics(SetOf):
393    _child_spec = TimingMetrics
394
395
396class TimingPolicy(Sequence):
397    _fields = [
398        ('policy_id', SequenceOf, {'spec': ObjectIdentifier}),
399        ('max_offset', BigTime, {'explicit': 0, 'optional': True}),
400        ('max_delay', BigTime, {'explicit': 1, 'optional': True}),
401    ]
402
403
404class SetOfTimingPolicy(SetOf):
405    _child_spec = TimingPolicy
406
407
408class AttCertAttributeType(ObjectIdentifier):
409    _map = {
410        '1.3.6.1.5.5.7.10.1': 'authentication_info',
411        '1.3.6.1.5.5.7.10.2': 'access_identity',
412        '1.3.6.1.5.5.7.10.3': 'charging_identity',
413        '1.3.6.1.5.5.7.10.4': 'group',
414        '2.5.4.72': 'role',
415        '2.5.4.55': 'clearance',
416        '1.3.6.1.4.1.601.10.4.1': 'timing_metrics',
417        '1.3.6.1.4.1.601.10.4.2': 'timing_policy',
418    }
419
420
421class AttCertAttribute(Sequence):
422    _fields = [
423        ('type', AttCertAttributeType),
424        ('values', None),
425    ]
426
427    _oid_specs = {
428        'authentication_info': SetOfSvceAuthInfo,
429        'access_identity': SetOfSvceAuthInfo,
430        'charging_identity': SetOfIetfAttrSyntax,
431        'group': SetOfIetfAttrSyntax,
432        'role': SetOfRoleSyntax,
433        'clearance': SetOfClearance,
434        'timing_metrics': SetOfTimingMetrics,
435        'timing_policy': SetOfTimingPolicy,
436    }
437
438    def _values_spec(self):
439        return self._oid_specs.get(self['type'].native, SetOfAny)
440
441    _spec_callbacks = {
442        'values': _values_spec
443    }
444
445
446class AttCertAttributes(SequenceOf):
447    _child_spec = AttCertAttribute
448
449
450class AttributeCertificateInfoV2(Sequence):
451    _fields = [
452        ('version', AttCertVersion),
453        ('holder', Holder),
454        ('issuer', AttCertIssuer),
455        ('signature', SignedDigestAlgorithm),
456        ('serial_number', Integer),
457        ('att_cert_validity_period', AttCertValidityPeriod),
458        ('attributes', AttCertAttributes),
459        ('issuer_unique_id', OctetBitString, {'optional': True}),
460        ('extensions', Extensions, {'optional': True}),
461    ]
462
463
464class AttributeCertificateV2(Sequence):
465    # Handle the situation where a V2 cert is encoded as V1
466    _bad_tag = 1
467
468    _fields = [
469        ('ac_info', AttributeCertificateInfoV2),
470        ('signature_algorithm', SignedDigestAlgorithm),
471        ('signature', OctetBitString),
472    ]
473
474
475class OtherCertificateFormat(Sequence):
476    _fields = [
477        ('other_cert_format', ObjectIdentifier),
478        ('other_cert', Any),
479    ]
480
481
482class CertificateChoices(Choice):
483    _alternatives = [
484        ('certificate', Certificate),
485        ('extended_certificate', ExtendedCertificate, {'implicit': 0}),
486        ('v1_attr_cert', AttributeCertificateV1, {'implicit': 1}),
487        ('v2_attr_cert', AttributeCertificateV2, {'implicit': 2}),
488        ('other', OtherCertificateFormat, {'implicit': 3}),
489    ]
490
491    def validate(self, class_, tag, contents):
492        """
493        Ensures that the class and tag specified exist as an alternative. This
494        custom version fixes parsing broken encodings there a V2 attribute
495        # certificate is encoded as a V1
496
497        :param class_:
498            The integer class_ from the encoded value header
499
500        :param tag:
501            The integer tag from the encoded value header
502
503        :param contents:
504            A byte string of the contents of the value - used when the object
505            is explicitly tagged
506
507        :raises:
508            ValueError - when value is not a valid alternative
509        """
510
511        super(CertificateChoices, self).validate(class_, tag, contents)
512        if self._choice == 2:
513            if AttCertVersion.load(Sequence.load(contents)[0].dump()).native == 'v2':
514                self._choice = 3
515
516
517class CertificateSet(SetOf):
518    _child_spec = CertificateChoices
519
520
521class ContentInfo(Sequence):
522    _fields = [
523        ('content_type', ContentType),
524        ('content', Any, {'explicit': 0, 'optional': True}),
525    ]
526
527    _oid_pair = ('content_type', 'content')
528    _oid_specs = {}
529
530
531class SetOfContentInfo(SetOf):
532    _child_spec = ContentInfo
533
534
535class EncapsulatedContentInfo(Sequence):
536    _fields = [
537        ('content_type', ContentType),
538        ('content', ParsableOctetString, {'explicit': 0, 'optional': True}),
539    ]
540
541    _oid_pair = ('content_type', 'content')
542    _oid_specs = {}
543
544
545class IssuerAndSerialNumber(Sequence):
546    _fields = [
547        ('issuer', Name),
548        ('serial_number', Integer),
549    ]
550
551
552class SignerIdentifier(Choice):
553    _alternatives = [
554        ('issuer_and_serial_number', IssuerAndSerialNumber),
555        ('subject_key_identifier', OctetString, {'implicit': 0}),
556    ]
557
558
559class DigestAlgorithms(SetOf):
560    _child_spec = DigestAlgorithm
561
562
563class CertificateRevocationLists(SetOf):
564    _child_spec = CertificateList
565
566
567class SCVPReqRes(Sequence):
568    _fields = [
569        ('request', ContentInfo, {'explicit': 0, 'optional': True}),
570        ('response', ContentInfo),
571    ]
572
573
574class OtherRevInfoFormatId(ObjectIdentifier):
575    _map = {
576        '1.3.6.1.5.5.7.16.2': 'ocsp_response',
577        '1.3.6.1.5.5.7.16.4': 'scvp',
578    }
579
580
581class OtherRevocationInfoFormat(Sequence):
582    _fields = [
583        ('other_rev_info_format', OtherRevInfoFormatId),
584        ('other_rev_info', Any),
585    ]
586
587    _oid_pair = ('other_rev_info_format', 'other_rev_info')
588    _oid_specs = {
589        'ocsp_response': OCSPResponse,
590        'scvp': SCVPReqRes,
591    }
592
593
594class RevocationInfoChoice(Choice):
595    _alternatives = [
596        ('crl', CertificateList),
597        ('other', OtherRevocationInfoFormat, {'implicit': 1}),
598    ]
599
600
601class RevocationInfoChoices(SetOf):
602    _child_spec = RevocationInfoChoice
603
604
605class SignerInfo(Sequence):
606    _fields = [
607        ('version', CMSVersion),
608        ('sid', SignerIdentifier),
609        ('digest_algorithm', DigestAlgorithm),
610        ('signed_attrs', CMSAttributes, {'implicit': 0, 'optional': True}),
611        ('signature_algorithm', SignedDigestAlgorithm),
612        ('signature', OctetString),
613        ('unsigned_attrs', CMSAttributes, {'implicit': 1, 'optional': True}),
614    ]
615
616
617class SignerInfos(SetOf):
618    _child_spec = SignerInfo
619
620
621class SignedData(Sequence):
622    _fields = [
623        ('version', CMSVersion),
624        ('digest_algorithms', DigestAlgorithms),
625        ('encap_content_info', None),
626        ('certificates', CertificateSet, {'implicit': 0, 'optional': True}),
627        ('crls', RevocationInfoChoices, {'implicit': 1, 'optional': True}),
628        ('signer_infos', SignerInfos),
629    ]
630
631    def _encap_content_info_spec(self):
632        # If the encap_content_info is version v1, then this could be a PKCS#7
633        # structure, or a CMS structure. CMS wraps the encoded value in an
634        # Octet String tag.
635
636        # If the version is greater than 1, it is definite CMS
637        if self['version'].native != 'v1':
638            return EncapsulatedContentInfo
639
640        # Otherwise, the ContentInfo spec from PKCS#7 will be compatible with
641        # CMS v1 (which only allows Data, an Octet String) and PKCS#7, which
642        # allows Any
643        return ContentInfo
644
645    _spec_callbacks = {
646        'encap_content_info': _encap_content_info_spec
647    }
648
649
650class OriginatorInfo(Sequence):
651    _fields = [
652        ('certs', CertificateSet, {'implicit': 0, 'optional': True}),
653        ('crls', RevocationInfoChoices, {'implicit': 1, 'optional': True}),
654    ]
655
656
657class RecipientIdentifier(Choice):
658    _alternatives = [
659        ('issuer_and_serial_number', IssuerAndSerialNumber),
660        ('subject_key_identifier', OctetString, {'implicit': 0}),
661    ]
662
663
664class KeyEncryptionAlgorithmId(ObjectIdentifier):
665    _map = {
666        '1.2.840.113549.1.1.1': 'rsaes_pkcs1v15',
667        '1.2.840.113549.1.1.7': 'rsaes_oaep',
668        '2.16.840.1.101.3.4.1.5': 'aes128_wrap',
669        '2.16.840.1.101.3.4.1.8': 'aes128_wrap_pad',
670        '2.16.840.1.101.3.4.1.25': 'aes192_wrap',
671        '2.16.840.1.101.3.4.1.28': 'aes192_wrap_pad',
672        '2.16.840.1.101.3.4.1.45': 'aes256_wrap',
673        '2.16.840.1.101.3.4.1.48': 'aes256_wrap_pad',
674    }
675
676    _reverse_map = {
677        'rsa': '1.2.840.113549.1.1.1',
678        'rsaes_pkcs1v15': '1.2.840.113549.1.1.1',
679        'rsaes_oaep': '1.2.840.113549.1.1.7',
680        'aes128_wrap': '2.16.840.1.101.3.4.1.5',
681        'aes128_wrap_pad': '2.16.840.1.101.3.4.1.8',
682        'aes192_wrap': '2.16.840.1.101.3.4.1.25',
683        'aes192_wrap_pad': '2.16.840.1.101.3.4.1.28',
684        'aes256_wrap': '2.16.840.1.101.3.4.1.45',
685        'aes256_wrap_pad': '2.16.840.1.101.3.4.1.48',
686    }
687
688
689class KeyEncryptionAlgorithm(_ForceNullParameters, Sequence):
690    _fields = [
691        ('algorithm', KeyEncryptionAlgorithmId),
692        ('parameters', Any, {'optional': True}),
693    ]
694
695    _oid_pair = ('algorithm', 'parameters')
696    _oid_specs = {
697        'rsaes_oaep': RSAESOAEPParams,
698    }
699
700
701class KeyTransRecipientInfo(Sequence):
702    _fields = [
703        ('version', CMSVersion),
704        ('rid', RecipientIdentifier),
705        ('key_encryption_algorithm', KeyEncryptionAlgorithm),
706        ('encrypted_key', OctetString),
707    ]
708
709
710class OriginatorIdentifierOrKey(Choice):
711    _alternatives = [
712        ('issuer_and_serial_number', IssuerAndSerialNumber),
713        ('subject_key_identifier', OctetString, {'implicit': 0}),
714        ('originator_key', PublicKeyInfo, {'implicit': 1}),
715    ]
716
717
718class OtherKeyAttribute(Sequence):
719    _fields = [
720        ('key_attr_id', ObjectIdentifier),
721        ('key_attr', Any),
722    ]
723
724
725class RecipientKeyIdentifier(Sequence):
726    _fields = [
727        ('subject_key_identifier', OctetString),
728        ('date', GeneralizedTime, {'optional': True}),
729        ('other', OtherKeyAttribute, {'optional': True}),
730    ]
731
732
733class KeyAgreementRecipientIdentifier(Choice):
734    _alternatives = [
735        ('issuer_and_serial_number', IssuerAndSerialNumber),
736        ('r_key_id', RecipientKeyIdentifier, {'implicit': 0}),
737    ]
738
739
740class RecipientEncryptedKey(Sequence):
741    _fields = [
742        ('rid', KeyAgreementRecipientIdentifier),
743        ('encrypted_key', OctetString),
744    ]
745
746
747class RecipientEncryptedKeys(SequenceOf):
748    _child_spec = RecipientEncryptedKey
749
750
751class KeyAgreeRecipientInfo(Sequence):
752    _fields = [
753        ('version', CMSVersion),
754        ('originator', OriginatorIdentifierOrKey, {'explicit': 0}),
755        ('ukm', OctetString, {'explicit': 1, 'optional': True}),
756        ('key_encryption_algorithm', KeyEncryptionAlgorithm),
757        ('recipient_encrypted_keys', RecipientEncryptedKeys),
758    ]
759
760
761class KEKIdentifier(Sequence):
762    _fields = [
763        ('key_identifier', OctetString),
764        ('date', GeneralizedTime, {'optional': True}),
765        ('other', OtherKeyAttribute, {'optional': True}),
766    ]
767
768
769class KEKRecipientInfo(Sequence):
770    _fields = [
771        ('version', CMSVersion),
772        ('kekid', KEKIdentifier),
773        ('key_encryption_algorithm', KeyEncryptionAlgorithm),
774        ('encrypted_key', OctetString),
775    ]
776
777
778class PasswordRecipientInfo(Sequence):
779    _fields = [
780        ('version', CMSVersion),
781        ('key_derivation_algorithm', KdfAlgorithm, {'implicit': 0, 'optional': True}),
782        ('key_encryption_algorithm', KeyEncryptionAlgorithm),
783        ('encrypted_key', OctetString),
784    ]
785
786
787class OtherRecipientInfo(Sequence):
788    _fields = [
789        ('ori_type', ObjectIdentifier),
790        ('ori_value', Any),
791    ]
792
793
794class RecipientInfo(Choice):
795    _alternatives = [
796        ('ktri', KeyTransRecipientInfo),
797        ('kari', KeyAgreeRecipientInfo, {'implicit': 1}),
798        ('kekri', KEKRecipientInfo, {'implicit': 2}),
799        ('pwri', PasswordRecipientInfo, {'implicit': 3}),
800        ('ori', OtherRecipientInfo, {'implicit': 4}),
801    ]
802
803
804class RecipientInfos(SetOf):
805    _child_spec = RecipientInfo
806
807
808class EncryptedContentInfo(Sequence):
809    _fields = [
810        ('content_type', ContentType),
811        ('content_encryption_algorithm', EncryptionAlgorithm),
812        ('encrypted_content', OctetString, {'implicit': 0, 'optional': True}),
813    ]
814
815
816class EnvelopedData(Sequence):
817    _fields = [
818        ('version', CMSVersion),
819        ('originator_info', OriginatorInfo, {'implicit': 0, 'optional': True}),
820        ('recipient_infos', RecipientInfos),
821        ('encrypted_content_info', EncryptedContentInfo),
822        ('unprotected_attrs', CMSAttributes, {'implicit': 1, 'optional': True}),
823    ]
824
825
826class SignedAndEnvelopedData(Sequence):
827    _fields = [
828        ('version', CMSVersion),
829        ('recipient_infos', RecipientInfos),
830        ('digest_algorithms', DigestAlgorithms),
831        ('encrypted_content_info', EncryptedContentInfo),
832        ('certificates', CertificateSet, {'implicit': 0, 'optional': True}),
833        ('crls', CertificateRevocationLists, {'implicit': 1, 'optional': True}),
834        ('signer_infos', SignerInfos),
835    ]
836
837
838class DigestedData(Sequence):
839    _fields = [
840        ('version', CMSVersion),
841        ('digest_algorithm', DigestAlgorithm),
842        ('encap_content_info', None),
843        ('digest', OctetString),
844    ]
845
846    def _encap_content_info_spec(self):
847        # If the encap_content_info is version v1, then this could be a PKCS#7
848        # structure, or a CMS structure. CMS wraps the encoded value in an
849        # Octet String tag.
850
851        # If the version is greater than 1, it is definite CMS
852        if self['version'].native != 'v1':
853            return EncapsulatedContentInfo
854
855        # Otherwise, the ContentInfo spec from PKCS#7 will be compatible with
856        # CMS v1 (which only allows Data, an Octet String) and PKCS#7, which
857        # allows Any
858        return ContentInfo
859
860    _spec_callbacks = {
861        'encap_content_info': _encap_content_info_spec
862    }
863
864
865class EncryptedData(Sequence):
866    _fields = [
867        ('version', CMSVersion),
868        ('encrypted_content_info', EncryptedContentInfo),
869        ('unprotected_attrs', CMSAttributes, {'implicit': 1, 'optional': True}),
870    ]
871
872
873class AuthenticatedData(Sequence):
874    _fields = [
875        ('version', CMSVersion),
876        ('originator_info', OriginatorInfo, {'implicit': 0, 'optional': True}),
877        ('recipient_infos', RecipientInfos),
878        ('mac_algorithm', HmacAlgorithm),
879        ('digest_algorithm', DigestAlgorithm, {'implicit': 1, 'optional': True}),
880        # This does not require the _spec_callbacks approach of SignedData and
881        # DigestedData since AuthenticatedData was not part of PKCS#7
882        ('encap_content_info', EncapsulatedContentInfo),
883        ('auth_attrs', CMSAttributes, {'implicit': 2, 'optional': True}),
884        ('mac', OctetString),
885        ('unauth_attrs', CMSAttributes, {'implicit': 3, 'optional': True}),
886    ]
887
888
889class AuthEnvelopedData(Sequence):
890    _fields = [
891        ('version', CMSVersion),
892        ('originator_info', OriginatorInfo, {'implicit': 0, 'optional': True}),
893        ('recipient_infos', RecipientInfos),
894        ('auth_encrypted_content_info', EncryptedContentInfo),
895        ('auth_attrs', CMSAttributes, {'implicit': 1, 'optional': True}),
896        ('mac', OctetString),
897        ('unauth_attrs', CMSAttributes, {'implicit': 2, 'optional': True}),
898    ]
899
900
901class CompressionAlgorithmId(ObjectIdentifier):
902    _map = {
903        '1.2.840.113549.1.9.16.3.8': 'zlib',
904    }
905
906
907class CompressionAlgorithm(Sequence):
908    _fields = [
909        ('algorithm', CompressionAlgorithmId),
910        ('parameters', Any, {'optional': True}),
911    ]
912
913
914class CompressedData(Sequence):
915    _fields = [
916        ('version', CMSVersion),
917        ('compression_algorithm', CompressionAlgorithm),
918        ('encap_content_info', EncapsulatedContentInfo),
919    ]
920
921    _decompressed = None
922
923    @property
924    def decompressed(self):
925        if self._decompressed is None:
926            if zlib is None:
927                raise SystemError('The zlib module is not available')
928            self._decompressed = zlib.decompress(self['encap_content_info']['content'].native)
929        return self._decompressed
930
931
932class RecipientKeyIdentifier(Sequence):
933    _fields = [
934        ('subjectKeyIdentifier', OctetString),
935        ('date', GeneralizedTime, {'optional': True}),
936        ('other', OtherKeyAttribute, {'optional': True}),
937    ]
938
939
940class SMIMEEncryptionKeyPreference(Choice):
941    _alternatives = [
942        ('issuer_and_serial_number', IssuerAndSerialNumber, {'implicit': 0}),
943        ('recipientKeyId', RecipientKeyIdentifier, {'implicit': 1}),
944        ('subjectAltKeyIdentifier', PublicKeyInfo, {'implicit': 2}),
945    ]
946
947
948class SMIMEEncryptionKeyPreferences(SetOf):
949    _child_spec = SMIMEEncryptionKeyPreference
950
951
952class SMIMECapabilityIdentifier(Sequence):
953    _fields = [
954        ('capability_id', EncryptionAlgorithmId),
955        ('parameters', Any, {'optional': True}),
956    ]
957
958
959class SMIMECapabilites(SequenceOf):
960    _child_spec = SMIMECapabilityIdentifier
961
962
963class SetOfSMIMECapabilites(SetOf):
964    _child_spec = SMIMECapabilites
965
966
967ContentInfo._oid_specs = {
968    'data': OctetString,
969    'signed_data': SignedData,
970    'enveloped_data': EnvelopedData,
971    'signed_and_enveloped_data': SignedAndEnvelopedData,
972    'digested_data': DigestedData,
973    'encrypted_data': EncryptedData,
974    'authenticated_data': AuthenticatedData,
975    'compressed_data': CompressedData,
976    'authenticated_enveloped_data': AuthEnvelopedData,
977}
978
979
980EncapsulatedContentInfo._oid_specs = {
981    'signed_data': SignedData,
982    'enveloped_data': EnvelopedData,
983    'signed_and_enveloped_data': SignedAndEnvelopedData,
984    'digested_data': DigestedData,
985    'encrypted_data': EncryptedData,
986    'authenticated_data': AuthenticatedData,
987    'compressed_data': CompressedData,
988    'authenticated_enveloped_data': AuthEnvelopedData,
989}
990
991
992CMSAttribute._oid_specs = {
993    'content_type': SetOfContentType,
994    'message_digest': SetOfOctetString,
995    'signing_time': SetOfTime,
996    'counter_signature': SignerInfos,
997    'signature_time_stamp_token': SetOfContentInfo,
998    'cms_algorithm_protection': SetOfCMSAlgorithmProtection,
999    'microsoft_nested_signature': SetOfContentInfo,
1000    'microsoft_time_stamp_token': SetOfContentInfo,
1001    'encrypt_key_pref': SMIMEEncryptionKeyPreferences,
1002    'smime_capabilities': SetOfSMIMECapabilites,
1003}
1004