589 lines
14 KiB
Python
589 lines
14 KiB
Python
#
|
|
# 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
|
|
#
|
|
# PKCS#9: Selected Attribute Types (Version 2.0)
|
|
#
|
|
# ASN.1 source from:
|
|
# https://www.rfc-editor.org/rfc/rfc2985.txt
|
|
#
|
|
|
|
from pyasn1.type import char
|
|
from pyasn1.type import constraint
|
|
from pyasn1.type import namedtype
|
|
from pyasn1.type import namedval
|
|
from pyasn1.type import opentype
|
|
from pyasn1.type import tag
|
|
from pyasn1.type import univ
|
|
from pyasn1.type import useful
|
|
|
|
from pyasn1_modules import rfc7292
|
|
from pyasn1_modules import rfc5958
|
|
from pyasn1_modules import rfc5652
|
|
from pyasn1_modules import rfc5280
|
|
|
|
|
|
def _OID(*components):
|
|
output = []
|
|
for x in tuple(components):
|
|
if isinstance(x, univ.ObjectIdentifier):
|
|
output.extend(list(x))
|
|
else:
|
|
output.append(int(x))
|
|
|
|
return univ.ObjectIdentifier(output)
|
|
|
|
|
|
MAX = float('inf')
|
|
|
|
|
|
# Imports from RFC 5280
|
|
|
|
AlgorithmIdentifier = rfc5280.AlgorithmIdentifier
|
|
|
|
Attribute = rfc5280.Attribute
|
|
|
|
EmailAddress = rfc5280.EmailAddress
|
|
|
|
Extensions = rfc5280.Extensions
|
|
|
|
Time = rfc5280.Time
|
|
|
|
X520countryName = rfc5280.X520countryName
|
|
|
|
X520SerialNumber = rfc5280.X520SerialNumber
|
|
|
|
|
|
# Imports from RFC 5652
|
|
|
|
ContentInfo = rfc5652.ContentInfo
|
|
|
|
ContentType = rfc5652.ContentType
|
|
|
|
Countersignature = rfc5652.Countersignature
|
|
|
|
MessageDigest = rfc5652.MessageDigest
|
|
|
|
SignerInfo = rfc5652.SignerInfo
|
|
|
|
SigningTime = rfc5652.SigningTime
|
|
|
|
|
|
# Imports from RFC 5958
|
|
|
|
EncryptedPrivateKeyInfo = rfc5958.EncryptedPrivateKeyInfo
|
|
|
|
|
|
# Imports from RFC 7292
|
|
|
|
PFX = rfc7292.PFX
|
|
|
|
|
|
# TODO:
|
|
# Need a place to import PKCS15Token; it does not yet appear in an RFC
|
|
|
|
|
|
# SingleAttribute is the same as Attribute in RFC 5280, except that the
|
|
# attrValues SET must have one and only one member
|
|
|
|
class AttributeType(univ.ObjectIdentifier):
|
|
pass
|
|
|
|
|
|
class AttributeValue(univ.Any):
|
|
pass
|
|
|
|
|
|
class AttributeValues(univ.SetOf):
|
|
pass
|
|
|
|
AttributeValues.componentType = AttributeValue()
|
|
|
|
|
|
class SingleAttributeValues(univ.SetOf):
|
|
pass
|
|
|
|
SingleAttributeValues.componentType = AttributeValue()
|
|
|
|
|
|
class SingleAttribute(univ.Sequence):
|
|
pass
|
|
|
|
SingleAttribute.componentType = namedtype.NamedTypes(
|
|
namedtype.NamedType('type', AttributeType()),
|
|
namedtype.NamedType('values',
|
|
AttributeValues().subtype(sizeSpec=constraint.ValueSizeConstraint(1, 1)),
|
|
openType=opentype.OpenType('type', rfc5280.certificateAttributesMap)
|
|
)
|
|
)
|
|
|
|
|
|
# CMSAttribute is the same as Attribute in RFC 5652, and CMSSingleAttribute
|
|
# is the companion where the attrValues SET must have one and only one member
|
|
|
|
CMSAttribute = rfc5652.Attribute
|
|
|
|
|
|
class CMSSingleAttribute(univ.Sequence):
|
|
pass
|
|
|
|
CMSSingleAttribute.componentType = namedtype.NamedTypes(
|
|
namedtype.NamedType('attrType', AttributeType()),
|
|
namedtype.NamedType('attrValues',
|
|
AttributeValues().subtype(sizeSpec=constraint.ValueSizeConstraint(1, 1)),
|
|
openType=opentype.OpenType('attrType', rfc5652.cmsAttributesMap)
|
|
)
|
|
)
|
|
|
|
|
|
# DirectoryString is the same as RFC 5280, except the length is limited to 255
|
|
|
|
class DirectoryString(univ.Choice):
|
|
pass
|
|
|
|
DirectoryString.componentType = namedtype.NamedTypes(
|
|
namedtype.NamedType('teletexString', char.TeletexString().subtype(
|
|
subtypeSpec=constraint.ValueSizeConstraint(1, 255))),
|
|
namedtype.NamedType('printableString', char.PrintableString().subtype(
|
|
subtypeSpec=constraint.ValueSizeConstraint(1, 255))),
|
|
namedtype.NamedType('universalString', char.UniversalString().subtype(
|
|
subtypeSpec=constraint.ValueSizeConstraint(1, 255))),
|
|
namedtype.NamedType('utf8String', char.UTF8String().subtype(
|
|
subtypeSpec=constraint.ValueSizeConstraint(1, 255))),
|
|
namedtype.NamedType('bmpString', char.BMPString().subtype(
|
|
subtypeSpec=constraint.ValueSizeConstraint(1, 255)))
|
|
)
|
|
|
|
|
|
# PKCS9String is DirectoryString with an additional choice of IA5String,
|
|
# and the SIZE is limited to 255
|
|
|
|
class PKCS9String(univ.Choice):
|
|
pass
|
|
|
|
PKCS9String.componentType = namedtype.NamedTypes(
|
|
namedtype.NamedType('ia5String', char.IA5String().subtype(
|
|
subtypeSpec=constraint.ValueSizeConstraint(1, 255))),
|
|
namedtype.NamedType('directoryString', DirectoryString())
|
|
)
|
|
|
|
|
|
# Upper Bounds
|
|
|
|
pkcs_9_ub_pkcs9String = univ.Integer(255)
|
|
|
|
pkcs_9_ub_challengePassword = univ.Integer(pkcs_9_ub_pkcs9String)
|
|
|
|
pkcs_9_ub_emailAddress = univ.Integer(pkcs_9_ub_pkcs9String)
|
|
|
|
pkcs_9_ub_friendlyName = univ.Integer(pkcs_9_ub_pkcs9String)
|
|
|
|
pkcs_9_ub_match = univ.Integer(pkcs_9_ub_pkcs9String)
|
|
|
|
pkcs_9_ub_signingDescription = univ.Integer(pkcs_9_ub_pkcs9String)
|
|
|
|
pkcs_9_ub_unstructuredAddress = univ.Integer(pkcs_9_ub_pkcs9String)
|
|
|
|
pkcs_9_ub_unstructuredName = univ.Integer(pkcs_9_ub_pkcs9String)
|
|
|
|
|
|
ub_name = univ.Integer(32768)
|
|
|
|
pkcs_9_ub_placeOfBirth = univ.Integer(ub_name)
|
|
|
|
pkcs_9_ub_pseudonym = univ.Integer(ub_name)
|
|
|
|
|
|
# Object Identifier Arcs
|
|
|
|
ietf_at = _OID(1, 3, 6, 1, 5, 5, 7, 9)
|
|
|
|
id_at = _OID(2, 5, 4)
|
|
|
|
pkcs_9 = _OID(1, 2, 840, 113549, 1, 9)
|
|
|
|
pkcs_9_mo = _OID(pkcs_9, 0)
|
|
|
|
smime = _OID(pkcs_9, 16)
|
|
|
|
certTypes = _OID(pkcs_9, 22)
|
|
|
|
crlTypes = _OID(pkcs_9, 23)
|
|
|
|
pkcs_9_oc = _OID(pkcs_9, 24)
|
|
|
|
pkcs_9_at = _OID(pkcs_9, 25)
|
|
|
|
pkcs_9_sx = _OID(pkcs_9, 26)
|
|
|
|
pkcs_9_mr = _OID(pkcs_9, 27)
|
|
|
|
|
|
# Object Identifiers for Syntaxes for use with LDAP-accessible directories
|
|
|
|
pkcs_9_sx_pkcs9String = _OID(pkcs_9_sx, 1)
|
|
|
|
pkcs_9_sx_signingTime = _OID(pkcs_9_sx, 2)
|
|
|
|
|
|
# Object Identifiers for object classes
|
|
|
|
pkcs_9_oc_pkcsEntity = _OID(pkcs_9_oc, 1)
|
|
|
|
pkcs_9_oc_naturalPerson = _OID(pkcs_9_oc, 2)
|
|
|
|
|
|
# Object Identifiers for matching rules
|
|
|
|
pkcs_9_mr_caseIgnoreMatch = _OID(pkcs_9_mr, 1)
|
|
|
|
pkcs_9_mr_signingTimeMatch = _OID(pkcs_9_mr, 2)
|
|
|
|
|
|
# PKCS #7 PDU
|
|
|
|
pkcs_9_at_pkcs7PDU = _OID(pkcs_9_at, 5)
|
|
|
|
pKCS7PDU = Attribute()
|
|
pKCS7PDU['type'] = pkcs_9_at_pkcs7PDU
|
|
pKCS7PDU['values'][0] = ContentInfo()
|
|
|
|
|
|
# PKCS #12 token
|
|
|
|
pkcs_9_at_userPKCS12 = _OID(2, 16, 840, 1, 113730, 3, 1, 216)
|
|
|
|
userPKCS12 = Attribute()
|
|
userPKCS12['type'] = pkcs_9_at_userPKCS12
|
|
userPKCS12['values'][0] = PFX()
|
|
|
|
|
|
# PKCS #15 token
|
|
|
|
pkcs_9_at_pkcs15Token = _OID(pkcs_9_at, 1)
|
|
|
|
# TODO: Once PKCS15Token can be imported, this can be included
|
|
#
|
|
# pKCS15Token = Attribute()
|
|
# userPKCS12['type'] = pkcs_9_at_pkcs15Token
|
|
# userPKCS12['values'][0] = PKCS15Token()
|
|
|
|
|
|
# PKCS #8 encrypted private key information
|
|
|
|
pkcs_9_at_encryptedPrivateKeyInfo = _OID(pkcs_9_at, 2)
|
|
|
|
encryptedPrivateKeyInfo = Attribute()
|
|
encryptedPrivateKeyInfo['type'] = pkcs_9_at_encryptedPrivateKeyInfo
|
|
encryptedPrivateKeyInfo['values'][0] = EncryptedPrivateKeyInfo()
|
|
|
|
|
|
# Electronic-mail address
|
|
|
|
pkcs_9_at_emailAddress = rfc5280.id_emailAddress
|
|
|
|
emailAddress = Attribute()
|
|
emailAddress['type'] = pkcs_9_at_emailAddress
|
|
emailAddress['values'][0] = EmailAddress()
|
|
|
|
|
|
# Unstructured name
|
|
|
|
pkcs_9_at_unstructuredName = _OID(pkcs_9, 2)
|
|
|
|
unstructuredName = Attribute()
|
|
unstructuredName['type'] = pkcs_9_at_unstructuredName
|
|
unstructuredName['values'][0] = PKCS9String()
|
|
|
|
|
|
# Unstructured address
|
|
|
|
pkcs_9_at_unstructuredAddress = _OID(pkcs_9, 8)
|
|
|
|
unstructuredAddress = Attribute()
|
|
unstructuredAddress['type'] = pkcs_9_at_unstructuredAddress
|
|
unstructuredAddress['values'][0] = DirectoryString()
|
|
|
|
|
|
# Date of birth
|
|
|
|
pkcs_9_at_dateOfBirth = _OID(ietf_at, 1)
|
|
|
|
dateOfBirth = SingleAttribute()
|
|
dateOfBirth['type'] = pkcs_9_at_dateOfBirth
|
|
dateOfBirth['values'][0] = useful.GeneralizedTime()
|
|
|
|
|
|
# Place of birth
|
|
|
|
pkcs_9_at_placeOfBirth = _OID(ietf_at, 2)
|
|
|
|
placeOfBirth = SingleAttribute()
|
|
placeOfBirth['type'] = pkcs_9_at_placeOfBirth
|
|
placeOfBirth['values'][0] = DirectoryString()
|
|
|
|
|
|
# Gender
|
|
|
|
class GenderString(char.PrintableString):
|
|
pass
|
|
|
|
GenderString.subtypeSpec = constraint.ValueSizeConstraint(1, 1)
|
|
GenderString.subtypeSpec = constraint.SingleValueConstraint("M", "F", "m", "f")
|
|
|
|
|
|
pkcs_9_at_gender = _OID(ietf_at, 3)
|
|
|
|
gender = SingleAttribute()
|
|
gender['type'] = pkcs_9_at_gender
|
|
gender['values'][0] = GenderString()
|
|
|
|
|
|
# Country of citizenship
|
|
|
|
pkcs_9_at_countryOfCitizenship = _OID(ietf_at, 4)
|
|
|
|
countryOfCitizenship = Attribute()
|
|
countryOfCitizenship['type'] = pkcs_9_at_countryOfCitizenship
|
|
countryOfCitizenship['values'][0] = X520countryName()
|
|
|
|
|
|
# Country of residence
|
|
|
|
pkcs_9_at_countryOfResidence = _OID(ietf_at, 5)
|
|
|
|
countryOfResidence = Attribute()
|
|
countryOfResidence['type'] = pkcs_9_at_countryOfResidence
|
|
countryOfResidence['values'][0] = X520countryName()
|
|
|
|
|
|
# Pseudonym
|
|
|
|
id_at_pseudonym = _OID(2, 5, 4, 65)
|
|
|
|
pseudonym = Attribute()
|
|
pseudonym['type'] = id_at_pseudonym
|
|
pseudonym['values'][0] = DirectoryString()
|
|
|
|
|
|
# Serial number
|
|
|
|
id_at_serialNumber = rfc5280.id_at_serialNumber
|
|
|
|
serialNumber = Attribute()
|
|
serialNumber['type'] = id_at_serialNumber
|
|
serialNumber['values'][0] = X520SerialNumber()
|
|
|
|
|
|
# Content type
|
|
|
|
pkcs_9_at_contentType = rfc5652.id_contentType
|
|
|
|
contentType = CMSSingleAttribute()
|
|
contentType['attrType'] = pkcs_9_at_contentType
|
|
contentType['attrValues'][0] = ContentType()
|
|
|
|
|
|
# Message digest
|
|
|
|
pkcs_9_at_messageDigest = rfc5652.id_messageDigest
|
|
|
|
messageDigest = CMSSingleAttribute()
|
|
messageDigest['attrType'] = pkcs_9_at_messageDigest
|
|
messageDigest['attrValues'][0] = MessageDigest()
|
|
|
|
|
|
# Signing time
|
|
|
|
pkcs_9_at_signingTime = rfc5652.id_signingTime
|
|
|
|
signingTime = CMSSingleAttribute()
|
|
signingTime['attrType'] = pkcs_9_at_signingTime
|
|
signingTime['attrValues'][0] = SigningTime()
|
|
|
|
|
|
# Random nonce
|
|
|
|
class RandomNonce(univ.OctetString):
|
|
pass
|
|
|
|
RandomNonce.subtypeSpec = constraint.ValueSizeConstraint(4, MAX)
|
|
|
|
|
|
pkcs_9_at_randomNonce = _OID(pkcs_9_at, 3)
|
|
|
|
randomNonce = CMSSingleAttribute()
|
|
randomNonce['attrType'] = pkcs_9_at_randomNonce
|
|
randomNonce['attrValues'][0] = RandomNonce()
|
|
|
|
|
|
# Sequence number
|
|
|
|
class SequenceNumber(univ.Integer):
|
|
pass
|
|
|
|
SequenceNumber.subtypeSpec = constraint.ValueRangeConstraint(1, MAX)
|
|
|
|
|
|
pkcs_9_at_sequenceNumber = _OID(pkcs_9_at, 4)
|
|
|
|
sequenceNumber = CMSSingleAttribute()
|
|
sequenceNumber['attrType'] = pkcs_9_at_sequenceNumber
|
|
sequenceNumber['attrValues'][0] = SequenceNumber()
|
|
|
|
|
|
# Countersignature
|
|
|
|
pkcs_9_at_counterSignature = rfc5652.id_countersignature
|
|
|
|
counterSignature = CMSAttribute()
|
|
counterSignature['attrType'] = pkcs_9_at_counterSignature
|
|
counterSignature['attrValues'][0] = Countersignature()
|
|
|
|
|
|
# Challenge password
|
|
|
|
pkcs_9_at_challengePassword = _OID(pkcs_9, 7)
|
|
|
|
challengePassword = SingleAttribute()
|
|
challengePassword['type'] = pkcs_9_at_challengePassword
|
|
challengePassword['values'][0] = DirectoryString()
|
|
|
|
|
|
# Extension request
|
|
|
|
class ExtensionRequest(Extensions):
|
|
pass
|
|
|
|
|
|
pkcs_9_at_extensionRequest = _OID(pkcs_9, 14)
|
|
|
|
extensionRequest = SingleAttribute()
|
|
extensionRequest['type'] = pkcs_9_at_extensionRequest
|
|
extensionRequest['values'][0] = ExtensionRequest()
|
|
|
|
|
|
# Extended-certificate attributes (deprecated)
|
|
|
|
class AttributeSet(univ.SetOf):
|
|
pass
|
|
|
|
AttributeSet.componentType = Attribute()
|
|
|
|
|
|
pkcs_9_at_extendedCertificateAttributes = _OID(pkcs_9, 9)
|
|
|
|
extendedCertificateAttributes = SingleAttribute()
|
|
extendedCertificateAttributes['type'] = pkcs_9_at_extendedCertificateAttributes
|
|
extendedCertificateAttributes['values'][0] = AttributeSet()
|
|
|
|
|
|
# Friendly name
|
|
|
|
class FriendlyName(char.BMPString):
|
|
pass
|
|
|
|
FriendlyName.subtypeSpec = constraint.ValueSizeConstraint(1, pkcs_9_ub_friendlyName)
|
|
|
|
|
|
pkcs_9_at_friendlyName = _OID(pkcs_9, 20)
|
|
|
|
friendlyName = SingleAttribute()
|
|
friendlyName['type'] = pkcs_9_at_friendlyName
|
|
friendlyName['values'][0] = FriendlyName()
|
|
|
|
|
|
# Local key identifier
|
|
|
|
pkcs_9_at_localKeyId = _OID(pkcs_9, 21)
|
|
|
|
localKeyId = SingleAttribute()
|
|
localKeyId['type'] = pkcs_9_at_localKeyId
|
|
localKeyId['values'][0] = univ.OctetString()
|
|
|
|
|
|
# Signing description
|
|
|
|
pkcs_9_at_signingDescription = _OID(pkcs_9, 13)
|
|
|
|
signingDescription = CMSSingleAttribute()
|
|
signingDescription['attrType'] = pkcs_9_at_signingDescription
|
|
signingDescription['attrValues'][0] = DirectoryString()
|
|
|
|
|
|
# S/MIME capabilities
|
|
|
|
class SMIMECapability(AlgorithmIdentifier):
|
|
pass
|
|
|
|
|
|
class SMIMECapabilities(univ.SequenceOf):
|
|
pass
|
|
|
|
SMIMECapabilities.componentType = SMIMECapability()
|
|
|
|
|
|
pkcs_9_at_smimeCapabilities = _OID(pkcs_9, 15)
|
|
|
|
smimeCapabilities = CMSSingleAttribute()
|
|
smimeCapabilities['attrType'] = pkcs_9_at_smimeCapabilities
|
|
smimeCapabilities['attrValues'][0] = SMIMECapabilities()
|
|
|
|
|
|
# Certificate Attribute Map
|
|
|
|
_certificateAttributesMapUpdate = {
|
|
# Attribute types for use with the "pkcsEntity" object class
|
|
pkcs_9_at_pkcs7PDU: ContentInfo(),
|
|
pkcs_9_at_userPKCS12: PFX(),
|
|
# TODO: Once PKCS15Token can be imported, this can be included
|
|
# pkcs_9_at_pkcs15Token: PKCS15Token(),
|
|
pkcs_9_at_encryptedPrivateKeyInfo: EncryptedPrivateKeyInfo(),
|
|
# Attribute types for use with the "naturalPerson" object class
|
|
pkcs_9_at_emailAddress: EmailAddress(),
|
|
pkcs_9_at_unstructuredName: PKCS9String(),
|
|
pkcs_9_at_unstructuredAddress: DirectoryString(),
|
|
pkcs_9_at_dateOfBirth: useful.GeneralizedTime(),
|
|
pkcs_9_at_placeOfBirth: DirectoryString(),
|
|
pkcs_9_at_gender: GenderString(),
|
|
pkcs_9_at_countryOfCitizenship: X520countryName(),
|
|
pkcs_9_at_countryOfResidence: X520countryName(),
|
|
id_at_pseudonym: DirectoryString(),
|
|
id_at_serialNumber: X520SerialNumber(),
|
|
# Attribute types for use with PKCS #10 certificate requests
|
|
pkcs_9_at_challengePassword: DirectoryString(),
|
|
pkcs_9_at_extensionRequest: ExtensionRequest(),
|
|
pkcs_9_at_extendedCertificateAttributes: AttributeSet(),
|
|
}
|
|
|
|
rfc5280.certificateAttributesMap.update(_certificateAttributesMapUpdate)
|
|
|
|
|
|
# CMS Attribute Map
|
|
|
|
# Note: pkcs_9_at_smimeCapabilities is not included in the map because
|
|
# the definition in RFC 5751 is preferred, which produces the same
|
|
# encoding, but it allows different parameters for SMIMECapability
|
|
# and AlgorithmIdentifier.
|
|
|
|
_cmsAttributesMapUpdate = {
|
|
# Attribute types for use in PKCS #7 data (a.k.a. CMS)
|
|
pkcs_9_at_contentType: ContentType(),
|
|
pkcs_9_at_messageDigest: MessageDigest(),
|
|
pkcs_9_at_signingTime: SigningTime(),
|
|
pkcs_9_at_randomNonce: RandomNonce(),
|
|
pkcs_9_at_sequenceNumber: SequenceNumber(),
|
|
pkcs_9_at_counterSignature: Countersignature(),
|
|
# Attributes for use in PKCS #12 "PFX" PDUs or PKCS #15 tokens
|
|
pkcs_9_at_friendlyName: FriendlyName(),
|
|
pkcs_9_at_localKeyId: univ.OctetString(),
|
|
pkcs_9_at_signingDescription: DirectoryString(),
|
|
# pkcs_9_at_smimeCapabilities: SMIMECapabilities(),
|
|
}
|
|
|
|
rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate)
|