blob: cc1ff20ce79b58c2404db9b38da856dd86a58bd6 [file] [log] [blame]
wbonde91513e2015-06-03 14:52:18 -04001# coding: utf-8
wbondea25fc22015-06-19 15:07:04 -04002
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 - EncryptedData()
12 - EnvelopedData()
13 - EnvelopedData()
14 - SignedAndEnvelopedData()
15 - SignedData()
16
17Other type classes are defined that help compose the types listed above.
18"""
19
wbonde91513e2015-06-03 14:52:18 -040020from __future__ import unicode_literals
wbonde91513e2015-06-03 14:52:18 -040021
22try:
23 import zlib
24except (ImportError):
25 zlib = None
26
27from .algos import (
28 DigestAlgorithm,
wbond59af99d2015-06-15 16:19:04 -040029 EncryptionAlgorithm,
wbonde91513e2015-06-03 14:52:18 -040030 HmacAlgorithm,
wbond59af99d2015-06-15 16:19:04 -040031 KdfAlgorithm,
32 SignedDigestAlgorithm,
wbonde91513e2015-06-03 14:52:18 -040033)
34from .core import (
35 Any,
36 Choice,
37 Enumerated,
38 GeneralizedTime,
39 Integer,
40 ObjectIdentifier,
41 OctetBitString,
42 OctetString,
43 Sequence,
44 SequenceOf,
45 SetOf,
46 UTCTime,
47)
48from .crl import CertificateList
49from .keys import PublicKeyInfo
50from .ocsp import OCSPResponse
wbonde91513e2015-06-03 14:52:18 -040051from .x509 import Attributes, Certificate, Extensions, GeneralNames, Name
52
53
54
55# These structures are taken from
56# ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-6.asc
57
58class ExtendedCertificateInfo(Sequence):
59 _fields = [
60 ('version', Integer),
61 ('certificate', Certificate),
62 ('attributes', Attributes),
63 ]
64
65class ExtendedCertificate(Sequence):
66 _fields = [
67 ('extended_certificate_info', ExtendedCertificateInfo),
68 ('signature_algorithm', SignedDigestAlgorithm),
69 ('signature', OctetBitString),
70 ]
71
72
73# These structures are taken from https://tools.ietf.org/html/rfc5652,
74# https://tools.ietf.org/html/rfc5083, http://tools.ietf.org/html/rfc2315,
75# https://tools.ietf.org/html/rfc5940, https://tools.ietf.org/html/rfc3274,
76# https://tools.ietf.org/html/rfc3281
77
78
79class CMSVersion(Integer):
80 _map = {
81 0: 'v0',
82 1: 'v1',
83 2: 'v2',
84 3: 'v3',
85 4: 'v4',
86 5: 'v5',
87 }
88
89
90class CMSAttributeType(ObjectIdentifier):
91 _map = {
92 '1.2.840.113549.1.9.3': 'content_type',
93 '1.2.840.113549.1.9.4': 'message_digest',
94 '1.2.840.113549.1.9.5': 'signing_time',
95 '1.2.840.113549.1.9.6': 'counter_signature',
96 }
97
98
99class Time(Choice):
100 _alternatives = [
101 ('utc_time', UTCTime),
102 ('generalized_time', GeneralizedTime),
103 ]
104
105
106class ContentType(ObjectIdentifier):
107 _map = {
108 '1.2.840.113549.1.7.1': 'data',
109 '1.2.840.113549.1.7.2': 'signed_data',
110 '1.2.840.113549.1.7.3': 'enveloped_data',
111 '1.2.840.113549.1.7.4': 'signed_and_enveloped_data',
112 '1.2.840.113549.1.7.5': 'digested_data',
113 '1.2.840.113549.1.7.6': 'encrypted_data',
114 '1.2.840.113549.1.9.16.1.2': 'authenticated_data',
115 '1.2.840.113549.1.9.16.1.9': 'compressed_data',
116 '1.2.840.113549.1.9.16.1.23': 'authenticated_enveloped_data',
117 }
118
119
120class SetOfContentType(SetOf):
121 _child_spec = ContentType
122
123
124class SetOfOctetString(SetOf):
125 _child_spec = OctetString
126
127
128class SetOfTime(SetOf):
129 _child_spec = Time
130
131
132class CMSAttribute(Sequence):
133 _fields = [
134 ('type', CMSAttributeType),
135 ('values', Any),
136 ]
137
138 _oid_pair = ('type', 'values')
139 _oid_specs = {}
140
141
142class CMSAttributes(SequenceOf):
143 _child_spec = CMSAttribute
144
145
146class IssuerSerial(Sequence):
147 _fields = [
148 ('issuer', GeneralNames),
149 ('serial', Integer),
150 ('issuer_uid', OctetBitString, {'optional': True}),
151 ]
152
153
154class AttCertVersion(Integer):
155 _map = {
156 0: 'v1',
157 1: 'v2',
158 }
159
160
161class AttCertSubject(Choice):
162 _alternatives = [
163 ('base_certificate_id', IssuerSerial, {'tag_type': 'explicit', 'tag': 0}),
164 ('subject_name', GeneralNames, {'tag_type': 'explicit', 'tag': 1}),
165 ]
166
167
168class AttCertValidityPeriod(Sequence):
169 _fields = [
170 ('not_before_time', GeneralizedTime),
171 ('not_after_time', GeneralizedTime),
172 ]
173
174
175class AttributeCertificateInfoV1(Sequence):
176 _fields = [
177 ('version', AttCertVersion, {'default', 'v1'}),
178 ('subject', AttCertSubject),
179 ('issuer', GeneralNames),
180 ('signature', SignedDigestAlgorithm),
181 ('serial_number', Integer),
182 ('att_cert_validity_period', AttCertValidityPeriod),
183 ('attributes', Attributes),
184 ('issuer_unique_id', OctetBitString, {'optional': True}),
185 ('extensions', Extensions, {'optional': True}),
186 ]
187
188
189class AttributeCertificateV1(Sequence):
190 _fields = [
191 ('ac_info', AttributeCertificateInfoV1),
192 ('signature_algorithm', SignedDigestAlgorithm),
193 ('signature', OctetBitString),
194 ]
195
196
197class DigestedObjectType(Enumerated):
198 _map = {
199 0: 'public_key',
200 1: 'public_key_cert',
201 2: 'other_objy_types',
202 }
203
204
205class ObjectDigestInfo(Sequence):
206 _fields = [
207 ('digested_object_type', DigestedObjectType),
208 ('other_object_type_id', ObjectIdentifier, {'optional': True}),
209 ('digest_algorithm', DigestAlgorithm),
210 ('object_digest', OctetBitString),
211 ]
212
213
214class Holder(Sequence):
215 _fields = [
216 ('base_certificate_id', IssuerSerial, {'tag_type': 'implicit', 'tag': 0, 'optional': True}),
217 ('entity_name', GeneralNames, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
218 ('object_digest_info', ObjectDigestInfo, {'tag_type': 'implicit', 'tag': 2, 'optional': True}),
219 ]
220
221
222class V2Form(Sequence):
223 _fields = [
224 ('issuer_name', GeneralNames, {'optional': True}),
225 ('base_certificate_id', IssuerSerial, {'tag_type': 'explicit', 'tag': 0, 'optional': True}),
226 ('object_digest_info', ObjectDigestInfo, {'tag_type': 'explicit', 'tag': 1, 'optional': True}),
227 ]
228
229
230class AttCertIssuer(Choice):
231 _alternatives = [
232 ('v1_form', GeneralNames),
233 ('v2_form', V2Form, {'tag_type': 'explicit', 'tag': 0}),
234 ]
235
236
237class AttributeCertificateInfoV2(Sequence):
238 _fields = [
239 ('version', AttCertVersion),
240 ('holder', Holder),
241 ('issuer', AttCertIssuer),
242 ('signature', SignedDigestAlgorithm),
243 ('serial_number', Integer),
244 ('att_cert_validity_period', AttCertValidityPeriod),
245 ('attributes', Attributes),
246 ('issuer_unique_id', OctetBitString, {'optional': True}),
247 ('extensions', Extensions, {'optional': True}),
248 ]
249
250
251class AttributeCertificateV2(Sequence):
252 _fields = [
253 ('ac_info', AttributeCertificateInfoV2),
254 ('signature_algorithm', SignedDigestAlgorithm),
255 ('signature', OctetBitString),
256 ]
257
258
259class OtherCertificateFormat(Sequence):
260 _fields = [
261 ('other_cert_format', ObjectIdentifier),
262 ('other_cert', Any),
263 ]
264
265
266class CertificateChoices(Choice):
267 _alternatives = [
268 ('certificate', Certificate),
269 ('extended_certificate', ExtendedCertificate, {'tag_type': 'implicit', 'tag': 0}),
270 ('v1_attr_cert', AttributeCertificateV1, {'tag_type': 'implicit', 'tag': 1}),
271 ('v2_attr_cert', AttributeCertificateV2, {'tag_type': 'implicit', 'tag': 2}),
272 ('other', OtherCertificateFormat, {'tag_type': 'implicit', 'tag': 3}),
273 ]
274
275
276class CertificateSet(SetOf):
277 _child_spec = CertificateChoices
278
279
280class ContentInfo(Sequence):
281 _fields = [
282 ('content_type', ContentType),
283 ('content', Any, {'tag_type': 'explicit', 'tag': 0, 'optional': True}),
284 ]
285
286 _oid_pair = ('content_type', 'content')
287 _oid_specs = {}
288
289
290class EncapsulatedContentInfo(Sequence):
291 _fields = [
292 ('content_type', ContentType),
293 ('content', OctetString, {'tag_type': 'explicit', 'tag': 0, 'optional': True}),
294 ]
295
296 _oid_pair = ('content_type', 'content')
297 _oid_specs = {}
298
299
300class IssuerAndSerialNumber(Sequence):
301 _fields = [
302 ('issuer', Name),
303 ('serial_number', Integer),
304 ]
305
306
307class SignerIdentifier(Choice):
308 _alternatives = [
309 ('issuer_and_serial_number', IssuerAndSerialNumber),
310 ('subject_key_identifier', OctetString, {'tag_type': 'implicit', 'tag': 0}),
311 ]
312
313
314class DigestAlgorithms(SetOf):
315 _child_spec = DigestAlgorithm
316
317
318class CertificateRevocationLists(SetOf):
319 _child_spec = CertificateList
320
321
322class SCVPReqRes(Sequence):
323 _fields = [
324 ('request', ContentInfo, {'tag_type': 'explicit', 'tag': 0, 'optional': True}),
325 ('response', ContentInfo),
326 ]
327
328
329class OtherRevInfoFormatId(ObjectIdentifier):
330 _map = {
331 '1.3.6.1.5.5.7.16.2': 'ocsp_response',
332 '1.3.6.1.5.5.7.16.4': 'scvp',
333 }
334
335
336class OtherRevocationInfoFormat(Sequence):
337 _fields = [
338 ('other_rev_info_format', OtherRevInfoFormatId),
339 ('other_rev_info', Any),
340 ]
341
342 _oid_pair = ('other_rev_info_format', 'other_rev_info')
343 _oid_specs = {
344 'ocsp_response': OCSPResponse,
345 'scvp': SCVPReqRes,
346 }
347
348
349class RevocationInfoChoice(Choice):
350 _alternatives = [
351 ('crl', CertificateList),
352 ('other', OtherRevocationInfoFormat, {'tag_type': 'implciit', 'tag': 1}),
353 ]
354
355
356class RevocationInfoChoices(SetOf):
357 _child_spec = RevocationInfoChoice
358
359
360class SignerInfo(Sequence):
361 _fields = [
362 ('version', CMSVersion),
363 ('sid', SignerIdentifier),
364 ('digest_algorithm', DigestAlgorithm),
365 ('signed_attrs', CMSAttributes, {'tag_type': 'implicit', 'tag': 0, 'optional': True}),
366 ('signature_algorithm', SignedDigestAlgorithm),
367 ('signature', OctetString),
368 ('unsigned_attrs', CMSAttributes, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
369 ]
370
371
372class SignerInfos(SetOf):
373 _child_spec = SignerInfo
374
375
376class SignedData(Sequence):
377 _fields = [
378 ('version', CMSVersion),
379 ('digest_algorithms', DigestAlgorithms),
380 ('encap_content_info', None),
381 ('certificates', CertificateSet, {'tag_type': 'implicit', 'tag': 0, 'optional': True}),
382 ('crls', RevocationInfoChoices, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
383 ('signer_infos', SignerInfos),
384 ]
385
386 def _encap_content_info_spec(self):
387 # If the encap_content_info is version v1, then this could be a PKCS#7
388 # structure, or a CMS structure. CMS wraps the encoded value in an
389 # Octet String tag.
390
391 # If the version is greater than 1, it is definite CMS
392 if self['version'].native != 'v1':
393 return EncapsulatedContentInfo
394
395 # Otherwise, the ContentInfo spec from PKCS#7 will be compatible with
396 # CMS v1 (which only allows Data, an Octet String) and PKCS#7, which
397 # allows Any
398 return ContentInfo
399
400 _spec_callbacks = {
401 'encap_content_info': _encap_content_info_spec
402 }
403
404
405class OriginatorInfo(Sequence):
406 _fields = [
407 ('certs', CertificateSet, {'tag_type': 'implicit', 'tag': 0, 'optional': True}),
408 ('crls', RevocationInfoChoices, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
409 ]
410
411
412class RecipientIdentifier(Choice):
413 _alternatives = [
414 ('issuer_and_serial_number', IssuerAndSerialNumber),
415 ('subject_key_identifier', OctetString, {'tag_type': 'implicit', 'tag': 0}),
416 ]
417
418
419class KeyEncryptionAlgorithmId(ObjectIdentifier):
420 _map = {
421 '1.2.840.113549.1.1.1': 'rsa'
422 }
423
424
425class KeyEncryptionAlgorithm(Sequence):
426 _fields = [
427 ('algorithm', KeyEncryptionAlgorithmId),
428 ('parameters', Any, {'optional': True}),
429 ]
430
431
432class KeyTransRecipientInfo(Sequence):
433 _fields = [
434 ('version', CMSVersion),
435 ('rid', RecipientIdentifier),
436 ('key_encryption_algorithm', KeyEncryptionAlgorithm),
437 ('encrypted_key', OctetString),
438 ]
439
440
441class OriginatorIdentifierOrKey(Choice):
442 _alternatives = [
443 ('issuer_and_serial_number', IssuerAndSerialNumber),
444 ('subject_key_identifier', OctetString, {'tag_type': 'implicit', 'tag': 0}),
445 ('originator_key', PublicKeyInfo, {'tag_type': 'implicit', 'tag': 1}),
446 ]
447
448
449class OtherKeyAttribute(Sequence):
450 _fields = [
451 ('key_attr_id', ObjectIdentifier),
452 ('key_attr', Any),
453 ]
454
455
456class RecipientKeyIdentifier(Sequence):
457 _fields = [
458 ('subject_key_identifier', OctetString),
459 ('date', GeneralizedTime, {'optional': True}),
460 ('other', OtherKeyAttribute, {'optional': True}),
461 ]
462
463
464class KeyAgreementRecipientIdentifier(Choice):
465 _alternatives = [
466 ('issuer_and_serial_number', IssuerAndSerialNumber),
467 ('r_key_id', RecipientKeyIdentifier, {'tag_type': 'implicit', 'tag': 0}),
468 ]
469
470
471class RecipientEncryptedKey(Sequence):
472 _fields = [
473 ('rid', KeyAgreementRecipientIdentifier),
474 ('encrypted_key', OctetString),
475 ]
476
477
478class RecipientEncryptedKeys(SequenceOf):
479 _child_spec = RecipientEncryptedKey
480
481
482class KeyAgreeRecipientInfo(Sequence):
483 _fields = [
484 ('version', CMSVersion),
485 ('originator', OriginatorIdentifierOrKey, {'tag_type': 'explicit', 'tag': 0}),
486 ('ukm', OctetString, {'tag_type': 'explicit', 'tag': 1, 'optional': True}),
487 ('key_encryption_algorithm', KeyEncryptionAlgorithm),
488 ('recipient_encrypted_keys', RecipientEncryptedKeys),
489 ]
490
491
492class KEKIdentifier(Sequence):
493 _fields = [
494 ('key_identifier', OctetString),
495 ('date', GeneralizedTime, {'optional': True}),
496 ('other', OtherKeyAttribute, {'optional': True}),
497 ]
498
499
500class KEKRecipientInfo(Sequence):
501 _fields = [
502 ('version', CMSVersion),
503 ('kekid', KEKIdentifier),
504 ('key_encryption_algorithm', KeyEncryptionAlgorithm),
505 ('encrypted_key', OctetString),
506 ]
507
508
509class PasswordRecipientInfo(Sequence):
510 _fields = [
511 ('version', CMSVersion),
512 ('key_derivation_algorithm', KdfAlgorithm, {'tag_type': 'implicit', 'tag': 0, 'optional': True}),
513 ('key_encryption_algorithm', KeyEncryptionAlgorithm),
514 ('encrypted_key', OctetString),
515 ]
516
517
518class OtherRecipientInfo(Sequence):
519 _fields = [
520 ('ori_type', ObjectIdentifier),
521 ('ori_value', Any),
522 ]
523
524
525class RecipientInfo(Choice):
526 _alternatives = [
527 ('ktri', KeyTransRecipientInfo),
528 ('kari', KeyAgreeRecipientInfo, {'tag_type': 'implicit', 'tag': 1}),
529 ('kekri', KEKRecipientInfo, {'tag_type': 'implicit', 'tag': 2}),
530 ('pwri', PasswordRecipientInfo, {'tag_type': 'implicit', 'tag': 3}),
531 ('ori', OtherRecipientInfo, {'tag_type': 'implicit', 'tag': 4}),
532 ]
533
534
535class RecipientInfos(SetOf):
536 _child_spec = RecipientInfo
537
538
539class EncryptedContentInfo(Sequence):
540 _fields = [
541 ('content_type', ContentType),
wbond59af99d2015-06-15 16:19:04 -0400542 ('content_encryption_algorithm', EncryptionAlgorithm),
wbonde91513e2015-06-03 14:52:18 -0400543 ('encrypted_content', OctetString, {'tag_type': 'implicit', 'tag': 0, 'optional': True}),
544 ]
545
546
547class EnvelopedData(Sequence):
548 _fields = [
549 ('version', CMSVersion),
550 ('originator_info', OriginatorInfo, {'tag_type': 'implicit', 'tag': 0, 'optional': True}),
551 ('recipient_infos', RecipientInfos),
552 ('encrypted_content_info', EncryptedContentInfo),
553 ('unprotected_attrs', CMSAttributes, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
554 ]
555
556
557class SignedAndEnvelopedData(Sequence):
558 _fields = [
559 ('version', CMSVersion),
560 ('recipient_infos', RecipientInfos),
561 ('digest_algorithms', DigestAlgorithms),
562 ('encrypted_content_info', EncryptedContentInfo),
563 ('certificates', CertificateSet, {'tag_type': 'implicit', 'tag': 0, 'optional': True}),
564 ('crls', CertificateRevocationLists, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
565 ('signer_infos', SignerInfos),
566 ]
567
568
569class DigestedData(Sequence):
570 _fields = [
571 ('version', CMSVersion),
572 ('digest_algorithm', DigestAlgorithm),
573 ('encap_content_info', None),
574 ('digest', OctetString),
575 ]
576
577 def _encap_content_info_spec(self):
578 # If the encap_content_info is version v1, then this could be a PKCS#7
579 # structure, or a CMS structure. CMS wraps the encoded value in an
580 # Octet String tag.
581
582 # If the version is greater than 1, it is definite CMS
583 if self['version'].native != 'v1':
584 return EncapsulatedContentInfo
585
586 # Otherwise, the ContentInfo spec from PKCS#7 will be compatible with
587 # CMS v1 (which only allows Data, an Octet String) and PKCS#7, which
588 # allows Any
589 return ContentInfo
590
591 _spec_callbacks = {
592 'encap_content_info': _encap_content_info_spec
593 }
594
595
596class EncryptedData(Sequence):
597 _fields = [
598 ('version', CMSVersion),
599 ('encrypted_content_info', EncryptedContentInfo),
600 ('unprotected_attrs', CMSAttributes, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
601 ]
602
603
604class AuthenticatedData(Sequence):
605 _fields = [
606 ('version', CMSVersion),
607 ('originator_info', OriginatorInfo, {'tag_type': 'implicit', 'tag': 0, 'optional': True}),
608 ('recipient_infos', RecipientInfos),
609 ('mac_algorithm', HmacAlgorithm),
610 ('digest_algorithm', DigestAlgorithm, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
611 # This does not require the _spec_callbacks approach of SignedData and
612 # DigestedData since AuthenticatedData was not part of PKCS#7
613 ('encap_content_info', EncapsulatedContentInfo),
614 ('auth_attrs', CMSAttributes, {'tag_type': 'implicit', 'tag': 2, 'optional': True}),
615 ('mac', OctetString),
616 ('unauth_attrs', CMSAttributes, {'tag_type': 'implicit', 'tag': 3, 'optional': True}),
617 ]
618
619
620class AuthEnvelopedData(Sequence):
621 _fields = [
622 ('version', CMSVersion),
623 ('originator_info', OriginatorInfo, {'tag_type': 'implicit', 'tag': 0, 'optional': True}),
624 ('recipient_infos', RecipientInfos),
625 ('auth_encrypted_content_info', EncryptedContentInfo),
626 ('auth_attrs', CMSAttributes, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
627 ('mac', OctetString),
628 ('unauth_attrs', CMSAttributes, {'tag_type': 'implicit', 'tag': 2, 'optional': True}),
629 ]
630
631
632class CompressionAlgorithmId(ObjectIdentifier):
633 _map = {
634 '1.2.840.113549.1.9.16.3.8': 'zlib',
635 }
636
637
638class CompressionAlgorithm(Sequence):
639 _fields = [
640 ('algorithm', CompressionAlgorithmId),
wbond40a32f02015-06-17 22:29:56 -0400641 ('parameters', Any, {'optional': True}),
wbonde91513e2015-06-03 14:52:18 -0400642 ]
643
644
645class CompressedData(Sequence):
646 _fields = [
647 ('version', CMSVersion),
648 ('compression_algorithm', CompressionAlgorithm),
649 ('encap_content_info', EncapsulatedContentInfo),
650 ]
651
652 _decompressed = None
653
654 @property
655 def decompressed(self):
656 if self._decompressed is None:
657 if zlib is None:
658 raise SystemError('The zlib module is not available')
659 self._decompressed = zlib.decompress(self['encap_content_info']['content'].native)
660 return self._decompressed
661
662
663ContentInfo._oid_specs = { #pylint: disable=W0212
664 'data': OctetString,
665 'signed_data': SignedData,
666 'enveloped_data': EnvelopedData,
667 'signed_and_enveloped_data': SignedAndEnvelopedData,
668 'digested_data': DigestedData,
669 'encrypted_data': EncryptedData,
670 'authenticated_data': AuthenticatedData,
671 'compressed_data': CompressedData,
672 'authenticated_enveloped_data': AuthEnvelopedData,
673}
674
675
676EncapsulatedContentInfo._oid_specs = { #pylint: disable=W0212
677 'signed_data': SignedData,
678 'enveloped_data': EnvelopedData,
679 'signed_and_enveloped_data': SignedAndEnvelopedData,
680 'digested_data': DigestedData,
681 'encrypted_data': EncryptedData,
682 'authenticated_data': AuthenticatedData,
683 'compressed_data': CompressedData,
684 'authenticated_enveloped_data': AuthEnvelopedData,
685}
686
687
688CMSAttribute._oid_specs = { #pylint: disable=W0212
689 'content_type': SetOfContentType,
690 'message_digest': SetOfOctetString,
691 'signing_time': SetOfTime,
692 'counter_signature': SignerInfos,
693}