1#
2# This file is part of pyasn1-modules software.
3#
4# Created by Russ Housley with assistance from asn1ate v.0.6.0.
5#
6# Copyright (c) 2019, Vigil Security, LLC
7# License: http://snmplabs.com/pyasn1/license.html
8#
9# PKCS#9: Selected Attribute Types (Version 2.0)
10#
11# ASN.1 source from:
12# https://www.rfc-editor.org/rfc/rfc2985.txt
13#
14
15from pyasn1.type import char
16from pyasn1.type import constraint
17from pyasn1.type import namedtype
18from pyasn1.type import namedval
19from pyasn1.type import opentype
20from pyasn1.type import tag
21from pyasn1.type import univ
22from pyasn1.type import useful
23
24from pyasn1_modules import rfc7292
25from pyasn1_modules import rfc5958
26from pyasn1_modules import rfc5652
27from pyasn1_modules import rfc5280
28
29
30def _OID(*components):
31    output = []
32    for x in tuple(components):
33        if isinstance(x, univ.ObjectIdentifier):
34            output.extend(list(x))
35        else:
36            output.append(int(x))
37
38    return univ.ObjectIdentifier(output)
39
40
41MAX = float('inf')
42
43
44# Imports from RFC 5280
45
46AlgorithmIdentifier = rfc5280.AlgorithmIdentifier
47
48Attribute = rfc5280.Attribute
49
50EmailAddress = rfc5280.EmailAddress
51
52Extensions = rfc5280.Extensions
53
54Time = rfc5280.Time
55
56X520countryName = rfc5280.X520countryName
57
58X520SerialNumber = rfc5280.X520SerialNumber
59
60
61# Imports from RFC 5652
62
63ContentInfo = rfc5652.ContentInfo
64
65ContentType = rfc5652.ContentType
66
67Countersignature = rfc5652.Countersignature
68
69MessageDigest = rfc5652.MessageDigest
70
71SignerInfo = rfc5652.SignerInfo
72
73SigningTime = rfc5652.SigningTime
74
75
76# Imports from RFC 5958
77
78EncryptedPrivateKeyInfo = rfc5958.EncryptedPrivateKeyInfo
79
80
81# Imports from RFC 7292
82
83PFX = rfc7292.PFX
84
85
86# TODO:
87# Need a place to import PKCS15Token; it does not yet appear in an RFC
88
89
90# SingleAttribute is the same as Attribute in RFC 5280, except that the
91# attrValues SET must have one and only one member
92
93class AttributeType(univ.ObjectIdentifier):
94    pass
95
96
97class AttributeValue(univ.Any):
98    pass
99
100
101class AttributeValues(univ.SetOf):
102    pass
103
104AttributeValues.componentType = AttributeValue()
105
106
107class SingleAttributeValues(univ.SetOf):
108    pass
109
110SingleAttributeValues.componentType = AttributeValue()
111
112
113class SingleAttribute(univ.Sequence):
114    pass
115
116SingleAttribute.componentType = namedtype.NamedTypes(
117    namedtype.NamedType('type', AttributeType()),
118    namedtype.NamedType('values',
119        AttributeValues().subtype(sizeSpec=constraint.ValueSizeConstraint(1, 1)),
120        openType=opentype.OpenType('type', rfc5280.certificateAttributesMap)
121    )
122)
123
124
125# CMSAttribute is the same as Attribute in RFC 5652, and CMSSingleAttribute
126# is the companion where the attrValues SET must have one and only one member
127
128CMSAttribute = rfc5652.Attribute
129
130
131class CMSSingleAttribute(univ.Sequence):
132    pass
133
134CMSSingleAttribute.componentType = namedtype.NamedTypes(
135    namedtype.NamedType('attrType', AttributeType()),
136    namedtype.NamedType('attrValues',
137        AttributeValues().subtype(sizeSpec=constraint.ValueSizeConstraint(1, 1)),
138        openType=opentype.OpenType('attrType', rfc5652.cmsAttributesMap)
139    )
140)
141
142
143# DirectoryString is the same as RFC 5280, except the length is limited to 255
144
145class DirectoryString(univ.Choice):
146    pass
147
148DirectoryString.componentType = namedtype.NamedTypes(
149    namedtype.NamedType('teletexString', char.TeletexString().subtype(
150        subtypeSpec=constraint.ValueSizeConstraint(1, 255))),
151    namedtype.NamedType('printableString', char.PrintableString().subtype(
152        subtypeSpec=constraint.ValueSizeConstraint(1, 255))),
153    namedtype.NamedType('universalString', char.UniversalString().subtype(
154        subtypeSpec=constraint.ValueSizeConstraint(1, 255))),
155    namedtype.NamedType('utf8String', char.UTF8String().subtype(
156        subtypeSpec=constraint.ValueSizeConstraint(1, 255))),
157    namedtype.NamedType('bmpString', char.BMPString().subtype(
158        subtypeSpec=constraint.ValueSizeConstraint(1, 255)))
159)
160
161
162# PKCS9String is DirectoryString with an additional choice of IA5String,
163# and the SIZE is limited to 255
164
165class PKCS9String(univ.Choice):
166    pass
167
168PKCS9String.componentType = namedtype.NamedTypes(
169    namedtype.NamedType('ia5String', char.IA5String().subtype(
170        subtypeSpec=constraint.ValueSizeConstraint(1, 255))),
171    namedtype.NamedType('directoryString', DirectoryString())
172)
173
174
175# Upper Bounds
176
177pkcs_9_ub_pkcs9String = univ.Integer(255)
178
179pkcs_9_ub_challengePassword = univ.Integer(pkcs_9_ub_pkcs9String)
180
181pkcs_9_ub_emailAddress = univ.Integer(pkcs_9_ub_pkcs9String)
182
183pkcs_9_ub_friendlyName = univ.Integer(pkcs_9_ub_pkcs9String)
184
185pkcs_9_ub_match = univ.Integer(pkcs_9_ub_pkcs9String)
186
187pkcs_9_ub_signingDescription = univ.Integer(pkcs_9_ub_pkcs9String)
188
189pkcs_9_ub_unstructuredAddress = univ.Integer(pkcs_9_ub_pkcs9String)
190
191pkcs_9_ub_unstructuredName = univ.Integer(pkcs_9_ub_pkcs9String)
192
193
194ub_name = univ.Integer(32768)
195
196pkcs_9_ub_placeOfBirth = univ.Integer(ub_name)
197
198pkcs_9_ub_pseudonym = univ.Integer(ub_name)
199
200
201# Object Identifier Arcs
202
203ietf_at = _OID(1, 3, 6, 1, 5, 5, 7, 9)
204
205id_at = _OID(2, 5, 4)
206
207pkcs_9 = _OID(1, 2, 840, 113549, 1, 9)
208
209pkcs_9_mo = _OID(pkcs_9, 0)
210
211smime = _OID(pkcs_9, 16)
212
213certTypes = _OID(pkcs_9, 22)
214
215crlTypes = _OID(pkcs_9, 23)
216
217pkcs_9_oc = _OID(pkcs_9, 24)
218
219pkcs_9_at = _OID(pkcs_9, 25)
220
221pkcs_9_sx = _OID(pkcs_9, 26)
222
223pkcs_9_mr = _OID(pkcs_9, 27)
224
225
226# Object Identifiers for Syntaxes for use with LDAP-accessible directories
227
228pkcs_9_sx_pkcs9String = _OID(pkcs_9_sx, 1)
229
230pkcs_9_sx_signingTime = _OID(pkcs_9_sx, 2)
231
232
233# Object Identifiers for object classes
234
235pkcs_9_oc_pkcsEntity = _OID(pkcs_9_oc, 1)
236
237pkcs_9_oc_naturalPerson = _OID(pkcs_9_oc, 2)
238
239
240# Object Identifiers for matching rules
241
242pkcs_9_mr_caseIgnoreMatch = _OID(pkcs_9_mr, 1)
243
244pkcs_9_mr_signingTimeMatch = _OID(pkcs_9_mr, 2)
245
246
247# PKCS #7 PDU
248
249pkcs_9_at_pkcs7PDU = _OID(pkcs_9_at, 5)
250
251pKCS7PDU = Attribute()
252pKCS7PDU['type'] = pkcs_9_at_pkcs7PDU
253pKCS7PDU['values'][0] = ContentInfo()
254
255
256# PKCS #12 token
257
258pkcs_9_at_userPKCS12 = _OID(2, 16, 840, 1, 113730, 3, 1, 216)
259
260userPKCS12 = Attribute()
261userPKCS12['type'] = pkcs_9_at_userPKCS12
262userPKCS12['values'][0] = PFX()
263
264
265# PKCS #15 token
266
267pkcs_9_at_pkcs15Token = _OID(pkcs_9_at, 1)
268
269# TODO: Once PKCS15Token can be imported, this can be included
270#
271# pKCS15Token = Attribute()
272# userPKCS12['type'] = pkcs_9_at_pkcs15Token
273# userPKCS12['values'][0] = PKCS15Token()
274
275
276# PKCS #8 encrypted private key information
277
278pkcs_9_at_encryptedPrivateKeyInfo = _OID(pkcs_9_at, 2)
279
280encryptedPrivateKeyInfo = Attribute()
281encryptedPrivateKeyInfo['type'] = pkcs_9_at_encryptedPrivateKeyInfo
282encryptedPrivateKeyInfo['values'][0] = EncryptedPrivateKeyInfo()
283
284
285# Electronic-mail address
286
287pkcs_9_at_emailAddress = rfc5280.id_emailAddress
288
289emailAddress = Attribute()
290emailAddress['type'] = pkcs_9_at_emailAddress
291emailAddress['values'][0] = EmailAddress()
292
293
294# Unstructured name
295
296pkcs_9_at_unstructuredName = _OID(pkcs_9, 2)
297
298unstructuredName = Attribute()
299unstructuredName['type'] = pkcs_9_at_unstructuredName
300unstructuredName['values'][0] = PKCS9String()
301
302
303# Unstructured address
304
305pkcs_9_at_unstructuredAddress = _OID(pkcs_9, 8)
306
307unstructuredAddress = Attribute()
308unstructuredAddress['type'] = pkcs_9_at_unstructuredAddress
309unstructuredAddress['values'][0] = DirectoryString()
310
311
312# Date of birth
313
314pkcs_9_at_dateOfBirth = _OID(ietf_at, 1)
315
316dateOfBirth = SingleAttribute()
317dateOfBirth['type'] = pkcs_9_at_dateOfBirth
318dateOfBirth['values'][0] = useful.GeneralizedTime()
319
320
321# Place of birth
322
323pkcs_9_at_placeOfBirth = _OID(ietf_at, 2)
324
325placeOfBirth = SingleAttribute()
326placeOfBirth['type'] = pkcs_9_at_placeOfBirth
327placeOfBirth['values'][0] = DirectoryString()
328
329
330# Gender
331
332class GenderString(char.PrintableString):
333    pass
334
335GenderString.subtypeSpec = constraint.ValueSizeConstraint(1, 1)
336GenderString.subtypeSpec = constraint.SingleValueConstraint("M", "F", "m", "f")
337
338
339pkcs_9_at_gender = _OID(ietf_at, 3)
340
341gender = SingleAttribute()
342gender['type'] = pkcs_9_at_gender
343gender['values'][0] = GenderString()
344
345
346# Country of citizenship
347
348pkcs_9_at_countryOfCitizenship = _OID(ietf_at, 4)
349
350countryOfCitizenship = Attribute()
351countryOfCitizenship['type'] = pkcs_9_at_countryOfCitizenship
352countryOfCitizenship['values'][0] = X520countryName()
353
354
355#  Country of residence
356
357pkcs_9_at_countryOfResidence = _OID(ietf_at, 5)
358
359countryOfResidence = Attribute()
360countryOfResidence['type'] = pkcs_9_at_countryOfResidence
361countryOfResidence['values'][0] = X520countryName()
362
363
364# Pseudonym
365
366id_at_pseudonym = _OID(2, 5, 4, 65)
367
368pseudonym = Attribute()
369pseudonym['type'] = id_at_pseudonym
370pseudonym['values'][0] = DirectoryString()
371
372
373# Serial number
374
375id_at_serialNumber = rfc5280.id_at_serialNumber
376
377serialNumber = Attribute()
378serialNumber['type'] = id_at_serialNumber
379serialNumber['values'][0] = X520SerialNumber()
380
381
382# Content type
383
384pkcs_9_at_contentType = rfc5652.id_contentType
385
386contentType = CMSSingleAttribute()
387contentType['attrType'] = pkcs_9_at_contentType
388contentType['attrValues'][0] = ContentType()
389
390
391# Message digest
392
393pkcs_9_at_messageDigest = rfc5652.id_messageDigest
394
395messageDigest = CMSSingleAttribute()
396messageDigest['attrType'] = pkcs_9_at_messageDigest
397messageDigest['attrValues'][0] = MessageDigest()
398
399
400# Signing time
401
402pkcs_9_at_signingTime = rfc5652.id_signingTime
403
404signingTime = CMSSingleAttribute()
405signingTime['attrType'] = pkcs_9_at_signingTime
406signingTime['attrValues'][0] = SigningTime()
407
408
409# Random nonce
410
411class RandomNonce(univ.OctetString):
412    pass
413
414RandomNonce.subtypeSpec = constraint.ValueSizeConstraint(4, MAX)
415
416
417pkcs_9_at_randomNonce = _OID(pkcs_9_at, 3)
418
419randomNonce = CMSSingleAttribute()
420randomNonce['attrType'] = pkcs_9_at_randomNonce
421randomNonce['attrValues'][0] = RandomNonce()
422
423
424# Sequence number
425
426class SequenceNumber(univ.Integer):
427    pass
428
429SequenceNumber.subtypeSpec = constraint.ValueRangeConstraint(1, MAX)
430
431
432pkcs_9_at_sequenceNumber = _OID(pkcs_9_at, 4)
433
434sequenceNumber = CMSSingleAttribute()
435sequenceNumber['attrType'] = pkcs_9_at_sequenceNumber
436sequenceNumber['attrValues'][0] = SequenceNumber()
437
438
439# Countersignature
440
441pkcs_9_at_counterSignature = rfc5652.id_countersignature
442
443counterSignature = CMSAttribute()
444counterSignature['attrType'] = pkcs_9_at_counterSignature
445counterSignature['attrValues'][0] = Countersignature()
446
447
448# Challenge password
449
450pkcs_9_at_challengePassword = _OID(pkcs_9, 7)
451
452challengePassword = SingleAttribute()
453challengePassword['type'] = pkcs_9_at_challengePassword
454challengePassword['values'][0] = DirectoryString()
455
456
457# Extension request
458
459class ExtensionRequest(Extensions):
460    pass
461
462
463pkcs_9_at_extensionRequest = _OID(pkcs_9, 14)
464
465extensionRequest = SingleAttribute()
466extensionRequest['type'] = pkcs_9_at_extensionRequest
467extensionRequest['values'][0] = ExtensionRequest()
468
469
470# Extended-certificate attributes (deprecated)
471
472class AttributeSet(univ.SetOf):
473    pass
474
475AttributeSet.componentType = Attribute()
476
477
478pkcs_9_at_extendedCertificateAttributes = _OID(pkcs_9, 9)
479
480extendedCertificateAttributes = SingleAttribute()
481extendedCertificateAttributes['type'] = pkcs_9_at_extendedCertificateAttributes
482extendedCertificateAttributes['values'][0] = AttributeSet()
483
484
485# Friendly name
486
487class FriendlyName(char.BMPString):
488    pass
489
490FriendlyName.subtypeSpec = constraint.ValueSizeConstraint(1, pkcs_9_ub_friendlyName)
491
492
493pkcs_9_at_friendlyName = _OID(pkcs_9, 20)
494
495friendlyName = SingleAttribute()
496friendlyName['type'] = pkcs_9_at_friendlyName
497friendlyName['values'][0] = FriendlyName()
498
499
500# Local key identifier
501
502pkcs_9_at_localKeyId = _OID(pkcs_9, 21)
503
504localKeyId = SingleAttribute()
505localKeyId['type'] = pkcs_9_at_localKeyId
506localKeyId['values'][0] = univ.OctetString()
507
508
509# Signing description
510
511pkcs_9_at_signingDescription = _OID(pkcs_9, 13)
512
513signingDescription = CMSSingleAttribute()
514signingDescription['attrType'] = pkcs_9_at_signingDescription
515signingDescription['attrValues'][0] = DirectoryString()
516
517
518# S/MIME capabilities
519
520class SMIMECapability(AlgorithmIdentifier):
521    pass
522
523
524class SMIMECapabilities(univ.SequenceOf):
525    pass
526
527SMIMECapabilities.componentType = SMIMECapability()
528
529
530pkcs_9_at_smimeCapabilities = _OID(pkcs_9, 15)
531
532smimeCapabilities = CMSSingleAttribute()
533smimeCapabilities['attrType'] = pkcs_9_at_smimeCapabilities
534smimeCapabilities['attrValues'][0] = SMIMECapabilities()
535
536
537# Certificate Attribute Map
538
539_certificateAttributesMapUpdate = {
540    # Attribute types for use with the "pkcsEntity" object class
541    pkcs_9_at_pkcs7PDU: ContentInfo(),
542    pkcs_9_at_userPKCS12: PFX(),
543    # TODO: Once PKCS15Token can be imported, this can be included
544    # pkcs_9_at_pkcs15Token: PKCS15Token(),
545    pkcs_9_at_encryptedPrivateKeyInfo: EncryptedPrivateKeyInfo(),
546    # Attribute types for use with the "naturalPerson" object class
547    pkcs_9_at_emailAddress: EmailAddress(),
548    pkcs_9_at_unstructuredName: PKCS9String(),
549    pkcs_9_at_unstructuredAddress: DirectoryString(),
550    pkcs_9_at_dateOfBirth: useful.GeneralizedTime(),
551    pkcs_9_at_placeOfBirth: DirectoryString(),
552    pkcs_9_at_gender: GenderString(),
553    pkcs_9_at_countryOfCitizenship: X520countryName(),
554    pkcs_9_at_countryOfResidence: X520countryName(),
555    id_at_pseudonym: DirectoryString(),
556    id_at_serialNumber: X520SerialNumber(),
557    # Attribute types for use with PKCS #10 certificate requests
558    pkcs_9_at_challengePassword: DirectoryString(),
559    pkcs_9_at_extensionRequest: ExtensionRequest(),
560    pkcs_9_at_extendedCertificateAttributes: AttributeSet(),
561}
562
563rfc5280.certificateAttributesMap.update(_certificateAttributesMapUpdate)
564
565
566# CMS Attribute Map
567
568# Note: pkcs_9_at_smimeCapabilities is not included in the map because
569#       the definition in RFC 5751 is preferred, which produces the same
570#       encoding, but it allows different parameters for SMIMECapability
571#       and AlgorithmIdentifier.
572
573_cmsAttributesMapUpdate = {
574    # Attribute types for use in PKCS #7 data (a.k.a. CMS)
575    pkcs_9_at_contentType: ContentType(),
576    pkcs_9_at_messageDigest: MessageDigest(),
577    pkcs_9_at_signingTime: SigningTime(),
578    pkcs_9_at_randomNonce: RandomNonce(),
579    pkcs_9_at_sequenceNumber: SequenceNumber(),
580    pkcs_9_at_counterSignature: Countersignature(),
581    # Attributes for use in PKCS #12 "PFX" PDUs or PKCS #15 tokens
582    pkcs_9_at_friendlyName: FriendlyName(),
583    pkcs_9_at_localKeyId: univ.OctetString(),
584    pkcs_9_at_signingDescription: DirectoryString(),
585    # pkcs_9_at_smimeCapabilities: SMIMECapabilities(),
586}
587
588rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate)
589