RFC 6025

ASN.1 Translation

πŸ“… published October 2010, from ietf

Title Block πŸ’–

RFC 6025: ASN.1 Translation πŸŽ€, by C. Wallace (Cygnacom Solutions) and C. Gardiner (BBN Technologies). It's Informational 🌸, not a Standards Track spec, and it was published in October 2010 πŸ“…. The header has no Obsoletes or Updates line, so it doesn't replace or update anything. ISSN 2070-1721 ✨


Abstract

okay so ASN.1 (Abstract Syntax Notation One) has been the go-to language across the IETF Security Area for ages 🫢 Some specs were written in an old version that's now deprecated, and others use the current version. And not every ASN.1 compiler can handle both syntaxes πŸ’€ This doc is here to help spec authors and implementers convert ASN.1 modules from one version to the other without changing the "bits on the wire" πŸ”₯ It is NOT a full ASN.1 tutorial, though! It focuses on the features used in Security Area specs, especially the ones that change between versions ✨


Status of This Memo

this one's not an Internet Standards Track spec, it's just published for info 🧚

It is still an IETF product πŸ’… and it reflects what the IETF community agreed on. It got public review and was approved by the Internet Engineering Steering Group (IESG). Not every IESG-approved doc is up for any level of Internet Standard, so check Section 2 of RFC 5741 if you're curious πŸ™ˆ

For the current status, errata, and how to send feedback, go to http://www.rfc-editor.org/info/rfc6025 🌈


Β© vibes: Copyright (c) 2010 IETF Trust and the persons identified as the document authors. All rights reserved πŸ’œ

This doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as they stood on the publication date. Please actually read those, bestie, because they explain your rights and restrictions πŸ“œ If you pull Code Components out of this doc, they must include the Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions. They come with no warranty, as the Simplified BSD License says 🫢


Table of Contents πŸ—‚οΈ

1.  Introduction . . . . . . . . . . . . . . . . . . . . . . . . .  3
  1.1.  Terminology  . . . . . . . . . . . . . . . . . . . . . . .  3
2.  ASN.1 Design Elements  . . . . . . . . . . . . . . . . . . . .  3
  2.1.  Open Types . . . . . . . . . . . . . . . . . . . . . . . .  3
    2.1.1.  ANY DEFINED BY . . . . . . . . . . . . . . . . . . . .  4
    2.1.2.  OCTET STRINGs and BIT STRINGs  . . . . . . . . . . . .  5
    2.1.3.  Information Object Classes . . . . . . . . . . . . . .  5
  2.2.  Constraints  . . . . . . . . . . . . . . . . . . . . . . .  8
    2.2.1.  Simple Table Constraints . . . . . . . . . . . . . . .  8
    2.2.2.  Component Relation Constraints . . . . . . . . . . . .  9
    2.2.3.  Content Constraints  . . . . . . . . . . . . . . . . . 11
  2.3.  Parameterization . . . . . . . . . . . . . . . . . . . . . 12
  2.4.  Versioning and Extensibility . . . . . . . . . . . . . . . 13
    2.4.1.  Extension Markers  . . . . . . . . . . . . . . . . . . 14
    2.4.2.  Version Brackets . . . . . . . . . . . . . . . . . . . 14
3.  Character Set Differences  . . . . . . . . . . . . . . . . . . 15
4.  ASN.1 Translation  . . . . . . . . . . . . . . . . . . . . . . 16
  4.1.  Downgrading from X.68x to X.208  . . . . . . . . . . . . . 16
  4.2.  Upgrading from X.208 to X.68x  . . . . . . . . . . . . . . 16
5.  Security Considerations  . . . . . . . . . . . . . . . . . . . 17
6.  References . . . . . . . . . . . . . . . . . . . . . . . . . . 18
  6.1.  Normative References . . . . . . . . . . . . . . . . . . . 18
  6.2.  Informative References . . . . . . . . . . . . . . . . . . 18

1. Introduction ✨

this doc is basically a tutorial for converting ASN.1 modules written with [CCITT.X208.1988] to [CCITT.X680.2002], or the other way around πŸ¦‹ It was motivated by [RFC5911] and [RFC5912], which have updated ASN.1 modules for a bunch of RFCs πŸ’…

The whole point is to help you translate ASN.1 between versions without changing the encoded results when you use the Basic Encoding Rules or Distinguished Encoding Rules [CCITT.X209.1988] [CCITT.X690.2002] πŸ”₯ Other encoding rules weren't considered, so don't go there with this doc πŸ™ˆ

Converting a new module to an older one is pretty mechanical, bestie 🧚 Most of the work is just deleting the new constructs. Going from an older module to a newer one is also fairly mechanical, as long as you don't try to move the constraints that live in the prose into the ASN.1 module. If you do want those constraints in the module, it can get complicated fast 😭

1.1. Terminology 🌸

this doc covers two versions of ASN.1. The old one (1988) is defined in one document, X.208. The newer one (1998, 2002) is spread across a series of documents: X.680, X.681, X.682, and X.683. To keep things simple, the whole series is called X.68x from here on. When a specific document from the series matters, the doc refers to it by name πŸ’–

2. ASN.1 Design Elements πŸŽ€

when you translate an ASN.1 module from X.208 syntax to X.68x syntax (or the reverse), a lot of definitions don't need to change, and some don't even benefit from it 🫢 Looking at the original modules that [RFC5911] and [RFC5912] updated, plus the revised modules in those docs, most changes fall into a few categories. This section walks through those categories πŸ‘‘

2.1. Open Types πŸ¦‹

protocols are often built to be flexible, so later specs can define the syntax and semantics of some features. For example, [RFC5280] defines the Extension structure, and tons of other specs define their own extensions πŸ’… X.208, X.68x, or both give you several mechanisms for this, and they're described below ✨

2.1.1. ANY DEFINED BY πŸ’œ

X.208 has the ANY DEFINED BY production for specifying open types πŸ”₯ It usually shows up in a SEQUENCE next to an OBJECT IDENTIFIER that says what kind of object is encoded. The ContentInfo structure from [RFC5652] (shown below) uses ANY DEFINED BY with an OBJECT IDENTIFIER field to identify and carry any kind of data. Every content type wrapped in a ContentInfo gets its own unique OBJECT IDENTIFIER, like the id-signedData shown below. The catch is that X.208 has no formal way to link a type to its type identifier 😭 Any links live in the module's comments or in the text of the associated doc πŸ™ˆ

-- from RFC 5652
ContentInfo ::= SEQUENCE {
    contentType ContentType,
    content [0] EXPLICIT ANY DEFINED BY contentType }

ContentType ::= OBJECT IDENTIFIER

id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
   us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 }

ANY DEFINED BY can also use an INTEGER to say what kind of object is encoded, like in this example from [RFC5280] 🧚

-- from RFC 5280
ExtensionAttribute ::=  SEQUENCE {
    extension-attribute-type [0] IMPLICIT INTEGER
        (0..ub-extension-attributes),
    extension-attribute-value [1]
        ANY DEFINED BY extension-attribute-type }

ANY DEFINED BY was deprecated back in 1994, but it's still showing up in active specs πŸ’€ The AttributeValue definition in [RFC5280] uses ANY with a DEFINED BY comment to tie the value to a type identifier field 🌈

-- from RFC 5280
AttributeTypeAndValue ::= SEQUENCE {
    type     AttributeType,
    value    AttributeValue }

AttributeType ::= OBJECT IDENTIFIER

AttributeValue ::= ANY -- DEFINED BY AttributeType

2.1.2. OCTET STRINGs and BIT STRINGs πŸ“

both X.208 and X.68x let you implement open types using OCTET STRINGs and BIT STRINGs as containers 🫢 The Extension and SubjectPublicKeyInfo definitions in [RFC5280] show how OCTET STRING and BIT STRING get used to carry information that's further defined using ASN.1 ✨

-- from RFC 5280
Extension  ::=  SEQUENCE  {
    extnID      OBJECT IDENTIFIER,
    critical    BOOLEAN DEFAULT FALSE,
    extnValue   OCTET STRING
    -- contains the DER encoding of an ASN.1 value
    -- corresponding to the extension type identified
    -- by extnID
}

SubjectPublicKeyInfo  ::=  SEQUENCE  {
     algorithm            AlgorithmIdentifier,
     subjectPublicKey     BIT STRING  }

In both cases, the prose says that the OBJECT IDENTIFIER right next to the field tells you what kind of structure is inside the OCTET STRING or BIT STRING value πŸ¦‹ For example, when extnID holds id-ce-basicConstraints, the extnValue field carries an encoded BasicConstraints inside the OCTET STRING. Here's a dump of an encoded extension that shows it πŸ‘‘

Tag Length      Value
30   15:         SEQUENCE {
06    3:           OBJECT IDENTIFIER basicConstraints (2 5 29 19)
01    1:           BOOLEAN TRUE
04    5:           OCTET STRING, encapsulates {
30    3:               SEQUENCE {
01    1:                 BOOLEAN TRUE
       :                 }
       :               }
       :           }

2.1.3. Information Object Classes

okay so information object classes are defined in [CCITT.X681.2002] πŸ“š and they're honestly so useful πŸ’– They let protocol designers link up pieces of data that are somehow associated with each other πŸ”— The most generic way to think about it is that an Information Object class is basically a database schema πŸ—‚οΈ, and Information Object Sets are the actual databases filled with data πŸ’…

Unlike type definitions, object classes with the same structure are not equivalent πŸ™ˆ So if you have:

FOO ::= TYPE-IDENTIFIER

BAR ::= TYPE-IDENTIFIER

then FOO and BAR are not interchangeable. Iykyk πŸ’€

TYPE-IDENTIFIER is one of the predefined information object classes in Annex A of [CCITT.X681.2002] ✨ It gives you a simple mapping from an OBJECT IDENTIFIER to a data type πŸ¦‹ The tag UNIQUE on &id means this value can only appear once in an Information Object Set, but multiple objects can still be defined with the same &id value πŸ€“

[RFC5911] uses the TYPE-IDENTIFIER construction to update the definition of ContentInfo, and it looks like this πŸŽ€

-- TYPE-IDENTIFIER definition from X.681
TYPE-IDENTIFIER ::= CLASS
{
    &id OBJECT IDENTIFIER UNIQUE,
    &Type
}
WITH SYNTAX {&Type IDENTIFIED BY &id}

-- from updated RFC 5652 module in [RFC5911]
CONTENT-TYPE ::= TYPE-IDENTIFIER
ContentType ::= CONTENT-TYPE.&id

ContentInfo ::= SEQUENCE {
    contentType        CONTENT-TYPE.
                    &id({ContentSet}),
    content            [0] EXPLICIT CONTENT-TYPE.
                    &Type({ContentSet}{@contentType})}

ContentSet CONTENT-TYPE ::= {
    --  Define the set of content types to be recognized.
    ct-Data | ct-SignedData | ct-EncryptedData | ct-EnvelopedData |
    ct-AuthenticatedData | ct-DigestedData, ... }

-- other CONTENT-TYPE instances not shown for brevity
ct-SignedData CONTENT-TYPE ::=
     { SignedData IDENTIFIED BY id-signedData}

This example shows off a bunch of stuff 😭 Here's the breakdown:

  • Definition of an information object class: TYPE-IDENTIFIER and CONTENT-TYPE are information object classes.
  • Definition of an information object, or an instance of an information object class: ct-SignedData is an information object.
  • Definition of an information object set: ContentSet is an information object set.
  • Usage of an information object: the definition of ContentInfo uses information from the CONTENT-TYPE information object class.
  • Defining constraints using an object set: both the contentType and content fields are constrained by ContentSet.

As I said above, TYPE-IDENTIFIER just associates an OBJECT IDENTIFIER with an arbitrary data type 🌸 CONTENT-TYPE is a TYPE-IDENTIFIER. The WITH SYNTAX component lets you write object definitions in a more natural-language way 🧚

ct-SignedData is the name of an information object that associates the identifier id-signedData with the data type SignedData πŸ’œ It's an instance of the CONTENT-TYPE information object class. The &Type field gets the value SignedData, and the &id field gets the value id-signedData. The example above uses the syntax from the WITH SYNTAX component of the TYPE-IDENTIFIER definition. An equivalent definition that skips the provided syntax looks like this:

ct-SignedData CONTENT-TYPE ::=
{
    &id id-signedData,
    &Type SignedData
}

ContentSet is the name of a set of information objects derived from the CONTENT-TYPE information object class πŸ“ The set has six information objects and it's extensible, as shown by the ellipsis (see Section 2.4, "Versioning and Extensibility") ✨

ContentInfo is defined using type information from an information object, which means the type of the contentType field is that of the &id field from CONTENT-TYPE 🧠 An equivalent definition is:

ContentType ::= OBJECT IDENTIFIER

Both fields in ContentInfo are constrained πŸ‘‘ The contentType field is constrained with a simple table constraint, which restricts the values to the ones from the matching field of the objects in ContentSet. The content field is constrained with a component relationship constraint. We'll get into constraints in the next section 🫢


2.2. Constraints

The X.68x versions of the ASN.1 specifications brought in the ability to use object information sets as part of the constraint on the values a field can take πŸ”₯ Simple table constraints restrict the set of values that can show up in a field. Component relation constraints restrict a field based on the contents of other fields in the type. Main character energy πŸ‘‘

2.2.1. Simple Table Constraints

Simple table constraints are used all over the place in [RFC5911] and [RFC5912] to limit implementer options πŸŽ€ (Although the constraints are almost always followed by or include extensibility markers, which means the parameters end up serving as information and not as hard limits πŸ™ˆ) Table constraints are defined in [CCITT.X682.2002].

Some ASN.1 compilers can use a simple table constraint to check that a field contains one of the legal values πŸ’…

The following example from [RFC5911] shows how table constraints clarify the intended usage of a particular field πŸ¦‹ The parameters show the types of attributes you'll typically find in the signedAttrs and unsignedAttrs fields. In this example the object sets are disjoint, but that isn't required. For instance, in [RFC5912] the CertExtensions and CrlExtensions sets overlap a bit 🌈

-- from updated RFC 5652 module in [RFC5911]
SignerInfo ::= SEQUENCE {
    version CMSVersion,
    sid SignerIdentifier,
    digestAlgorithm DigestAlgorithmIdentifier,
    signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
    signatureAlgorithm SignatureAlgorithmIdentifier,
    signature SignatureValue,
    unsignedAttrs [1] IMPLICIT Attributes
         {{UnsignedAttributes}} OPTIONAL }

SignedAttributes ::= Attributes {{ SignedAttributesSet }}
SignedAttributesSet ATTRIBUTE ::=
       { aa-signingTime | aa-messageDigest | aa-contentType, ... }

UnsignedAttributes ATTRIBUTE ::= { aa-countersignature, ... }

2.2.2. Component Relation Constraints

Component relation constraints are often used to bind the type field of an open type to the identifier field πŸ”— Binding it this way lets a compiler decode the associated type right away when the containing structure is defined ⭐ The following example from [RFC2560], as updated in [RFC5912], shows this in action 🧚

-- from updated RFC 2560 module in [RFC5912]
RESPONSE ::= TYPE-IDENTIFIER

ResponseSet RESPONSE ::= {basicResponse, ...}

ResponseBytes ::=       SEQUENCE {
    responseType        RESPONSE.
                            &id ({ResponseSet}),
    response            OCTET STRING (CONTAINING RESPONSE.
                            &Type({ResponseSet}{@responseType}))}

Here the response field is constrained to contain a type identified by the responseType field πŸ’– The controlling field is pointed at using atNotation, e.g., "@responseType". atNotation can be defined relative to the outermost SEQUENCE, SET, or CHOICE, or relative to the field the atNotation is attached to. When there is no '.' right after the '@', the field is a member of the outermost SEQUENCE, SET, or CHOICE. When there is a '.' right after the '@', each '.' stands for a SEQUENCE, SET, or CHOICE, starting with the one that contains the field the atNotation is attached to. For example, ResponseBytes could also be written like this 🫢 The syntax is pretty similar here because the innermost and outermost SEQUENCE, SET, or CHOICE are the same:

ResponseBytes ::=       SEQUENCE {
    responseType        RESPONSE.
                            &id ({ResponseSet}),
    response            OCTET STRING (CONTAINING RESPONSE.
                            &Type({ResponseSet}{@.responseType}))}

The TaggedRequest example from [RFC5912] shows a case where the outermost and innermost SEQUENCE, SET, or CHOICE are different 🌸 For the atNotation in the requestMessageValue field definition, the outermost SEQUENCE, SET, or CHOICE is TaggedRequest, and the innermost one is the SEQUENCE used to define the orm field.

TaggedRequest ::= CHOICE {
   tcr               [0] TaggedCertificationRequest,
   crm               [1] CertReqMsg,
   orm               [2] SEQUENCE {
       bodyPartID            BodyPartID,
       requestMessageType    OTHER-REQUEST.&id({OtherRequests}),
       requestMessageValue   OTHER-REQUEST.&Type({OtherRequests}
                                 {@.requestMessageType})
   }
}
When you reference a field using atNotation, the definition of that field has to be included within the outermost SEQUENCE, SET, or CHOICE. References to fields inside structures that are defined separately are not allowed 🚫 This is a big one, bestie.

For example, the following shows invalid atNotation in the definition of the signature field inside the SIGNED parameterized type πŸ’€

AlgorithmIdentifier{ALGORITHM-TYPE, ALGORITHM-TYPE:AlgorithmSet} ::=
          SEQUENCE {
              algorithm   ALGORITHM-TYPE.&id({AlgorithmSet}),
              parameters  ALGORITHM-TYPE.
                     &Params({AlgorithmSet}{@algorithm}) OPTIONAL
          }

-- example containing invalid atNotation
SIGNED{ToBeSigned} ::= SEQUENCE {
   toBeSigned           ToBeSigned,
   algorithmIdentifier  AlgorithmIdentifier
                            { SIGNATURE-ALGORITHM, {...}}
   },
   signature BIT STRING (CONTAINING SIGNATURE-ALGORITHM.&Value(
                            {SignatureAlgorithms}
                            {@algorithmIdentifier.algorithm}))
}

Alternatively, the example above can be written with correct atNotation, with the definition of the algorithm field included within ToBeSigned πŸŽ€

  SIGNED{ToBeSigned} ::= SEQUENCE {
     toBeSigned           ToBeSigned,
     algorithmIdentifier  SEQUENCE {
         algorithm        SIGNATURE-ALGORITHM.
                              &id({SignatureAlgorithms}),
         parameters       SIGNATURE-ALGORITHM.
                              &Params({SignatureAlgorithms}
                                  {@algorithmIdentifier.algorithm})
     },
     signature BIT STRING (CONTAINING SIGNATURE-ALGORITHM.&Value(
                              {SignatureAlgorithms}
                              {@algorithmIdentifier.algorithm}))
  }

In the example above, the outermost SEQUENCE, SET, or CHOICE relative to the parameters field is the SIGNED parameterized type. The innermost structure is the SEQUENCE used as the type for the algorithmIdentifier field 🧁 The atNotation for the parameters field can be written in either of these two ways:

@algorithmIdentifier.algorithm

@.algorithm

The atNotation for the signature field has only one representation πŸ¦‹

2.2.3. Content Constraints πŸ’–

okay so open types stored as OCTET STRINGs or BIT STRINGs can get their own constraints using the content constraints syntax from [CCITT.X682.2002] ✨ here are the updated definitions from [RFC5911] and [RFC5912], and they show OCTET STRING and BIT STRING working together with restricted sets of identifiers πŸŽ€ the Extension definition is the main character here: its content constraint says the OCTET STRING has to be an encoding of whatever type is linked to the information object picked out of the ExtensionSet object set, using the value of the extnID field 🫢 SubjectPublicKeyInfo is the plot twist 😭 it uses prose to tie the BIT STRING to the type identifier, because for reasons covered in Section 2.2.2, "Component Relation Constraints", you can't write a content constraint that also includes a component relationship constraint to link the type value inside the algorithm field to the subjectPublicKey field πŸ™ˆ

   -- from updated RFC 5280 module in [RFC5912]
   Extension{EXTENSION:ExtensionSet} ::= SEQUENCE {
       extnID      EXTENSION.&id({ExtensionSet}),
       critical    BOOLEAN
       -- (EXTENSION.&Critical({ExtensionSet}{@extnID}))
                          DEFAULT FALSE,
       extnValue   OCTET STRING (CONTAINING
                     EXTENSION.&ExtnType({ExtensionSet}{@extnID}))
                     --  contains the DER encoding of the ASN.1 value
                     --  corresponding to the extension type identified
                     --  by extnID
   }

   SubjectPublicKeyInfo  ::=  SEQUENCE  {
       algorithm            AlgorithmIdentifier{PUBLIC-KEY,
                                {PublicKeyAlgorithms}},
       subjectPublicKey     BIT STRING
   }

2.3. Parameterization πŸŽ€

parameterization is defined in [CCITT.X683.2002] and it can also make brand-new types, kind of like the macro notation in Annex A of X.208 ✨ this example from [RFC5912] shows it in action: the toBeSigned field takes whatever type gets passed in as a parameter πŸ’…

   -- from [RFC5912]
   SIGNED{ToBeSigned} ::= SEQUENCE {
       toBeSigned  ToBeSigned,
       algorithm   AlgorithmIdentifier{SIGNATURE-ALGORITHM,
                       {SignatureAlgorithms}},
       signature   BIT STRING
   }

   -- from updated RFC5280 module in [RFC5912]
   Certificate  ::=  SIGNED{TBSCertificate}

parameters don't have to be simple types πŸ‘‘ the next example uses an information object class and an information object set as parameters πŸ¦‹ the first parameter in the AlgorithmIdentifier definition is an information object class, and any class used for it must have &id and &Params fields, which decide the type of the algorithm and parameters fields 🌸 other fields can show up in the class too, but AlgorithmIdentifier doesn't use them, as the SIGNATURE-ALGORITHM class below proves πŸ’€ the second parameter is an information object set that limits the values allowed in the algorithm and parameters fields πŸ“

   -- from [RFC5912]
   AlgorithmIdentifier{ALGORITHM-TYPE, ALGORITHM-TYPE:AlgorithmSet}
       ::= SEQUENCE
   {
       algorithm   ALGORITHM-TYPE.&id({AlgorithmSet}),
       parameters  ALGORITHM-TYPE.&Params
                     ({AlgorithmSet}{@algorithm}) OPTIONAL
   }

   SIGNATURE-ALGORITHM ::= CLASS {
       &id             OBJECT IDENTIFIER,
       &Params         OPTIONAL,
       &Value          OPTIONAL,
       &paramPresence  ParamOptions DEFAULT absent,
       &HashSet        DIGEST-ALGORITHM OPTIONAL,
       &PublicKeySet   PUBLIC-KEY OPTIONAL,
       &smimeCaps      SMIME-CAPS OPTIONAL
   } WITH SYNTAX {
       IDENTIFIER &id
       [VALUE &Value]
       [PARAMS [TYPE &Params] ARE &paramPresence ]
       [HASHES &HashSet]
       [PUBLIC KEYS &PublicKeySet]
       [SMIME CAPS &smimeCaps]
   }

   -- from updated RFC 2560 module in [RFC5912]
   BasicOCSPResponse       ::= SEQUENCE {
       tbsResponseData      ResponseData,
       signatureAlgorithm   AlgorithmIdentifier{SIGNATURE-ALGORITHM,
                             {sa-dsaWithSHA1 | sa-rsaWithSHA1 |
                                  sa-rsaWithMD5 | sa-rsaWithMD2, ...}},
       signature            BIT STRING,
       certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
   }

2.4. Versioning and Extensibility 🌈

specs get revised all the time and ASN.1 modules get new components, so ya need a way to stay flexible ✨ [CCITT.X681.2002] gives you two tools for that: extension markers and version brackets πŸ’œ

2.4.1. Extension Markers πŸ¦‹

an extension marker is just an ellipsis, which is three periods in a row 🫢 protocol designers drop them wherever they think things might change later πŸ‘€ you can get the same effect by putting EXTENSIBILITY IMPLIED in the ASN.1 module definition, which basically means every type in the module has an extension marker πŸ”₯ extensibility markers show up all over [RFC5911] and [RFC5912] wherever object sets are defined πŸ’… in some other spots, the updated modules added markers after the fact, in places where fields got added by an update to an earlier version, like the CertificateChoices example below πŸ™ˆ

examples:

   -- from updated RFC 3370 module in [RFC5911]
   KeyAgreementAlgs KEY-AGREE ::= { kaa-esdh | kaa-ssdh, ...}

   -- from updated RFC 5652 module in [RFC5911]
   CertificateChoices ::= CHOICE {
       certificate Certificate,
       extendedCertificate [0] IMPLICIT ExtendedCertificate,
            -- Obsolete
       ...,
       [[3: v1AttrCert [1] IMPLICIT AttributeCertificateV1]],
            -- Obsolete
       [[4: v2AttrCert [2] IMPLICIT AttributeCertificateV2]],
       [[5: other      [3] IMPLICIT OtherCertificateFormat]]
   }

protocol designers should use extension markers in definitions that are likely to change 🌸 for example, you should put extensibility markers on enumerated error values πŸ“

2.4.2. Version Brackets 🧚

version brackets are how you show which features only exist in later versions of an ASN.1 module and not the earlier ones ✨ [RFC5912] used them in TBSCertificate to add the issuerUniqueID, subjectUniqueID, and extensions fields, as you can see below πŸ’–

   -- from updated RFC 5280 module in [RFC5912]
   TBSCertificate  ::=  SEQUENCE  {
       version         [0]  Version DEFAULT v1,
       serialNumber         CertificateSerialNumber,
       signature            AlgorithmIdentifier{SIGNATURE-ALGORITHM,
                                 {SignatureAlgorithms}},
       issuer               Name,
       validity             Validity,
       subject              Name,
       subjectPublicKeyInfo SubjectPublicKeyInfo,
       ... ,
       [[2:               -- If present, version MUST be v2
       issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
       subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL
       ]],
       [[3:               -- If present, version MUST be v3 --
       extensions      [3]  ExtensionSet{{CertExtensions}} OPTIONAL
       ]], ... }

3. Character Set Differences πŸ”€

X.68s uses a character set that's a superset of the one defined in X.208 ✨ the X.208 set includes these:

      A to Z

      a to z

      0 to 9

      :=,{}<.

      ()[]-'"

the X.68x set adds these on top πŸ’œ

      !&*/;>@^_|

the > and | characters can also show up in X.208 syntax inside macro definitions πŸŽ€


4. ASN.1 Translation πŸ¦„

4.1. Downgrading from X.68x to X.208 🌷

at the very least, downgrading an ASN.1 module from X.68x syntax to X.208 means removing the features X.208 doesn't support 😀 the stuff IETF Security Area ASN.1 modules use most is information object classes (and object sets), content constraints, parameterization, extension markers, and version brackets πŸ’… extension markers and version brackets can just get deleted (or commented out) ✨ information object class and object set definitions can get deleted or commented out too, since nothing will be using them anymore 🧹 this checklist works for most cases:

  • Remove all Information Set Class, Information Set Object, and Information Set Object Set definitions and imports from the file.
  • Replace all fixed Type Information Set Class element references with the fixed type. (That is, replace FOO.&id with OBJECT IDENTIFIER.)
  • Delete all simple constraints.
  • Delete all CONTAINING statements.
  • Replace all variable Type Information Set Class element references with either ANY or ANY DEFINED BY statements.
  • Remove version and extension markers.
  • Manually enforce all instances of parameterized types.

4.2. Upgrading from X.208 to X.68x πŸš€

how much you change when upgrading from X.208 syntax to X.68x depends on why you're doing it and on your personal style πŸ’– a minimalist move would be fixing any deprecated features (mostly ANY DEFINED BY) and adding whatever extensibility markers you need 🌸 a more comprehensive glow-up might bring in constraints, parameterization, versioning, extensibility, and so on πŸ’…

this checklist works when you upgrade a module without adding constraints:

  • Use TYPE-IDENTIFIER.&Type for "ANY".
  • Use TYPE-IDENTIFIER.&Type for "ANY DEFINED BY ...".

when you do add constraints during an upgrade, there are extra steps:

  1. Identify each unique class that should be defined based on what types of things exist.
  2. Define an Information Object Class for each of the classes above with the appropriate elements.
  3. Define all of the appropriate Information Object Sets based on the classes defined in step 2 along with the different places that they should be used.
  4. Replace ANY by the appropriate class and variable type element.
  5. Replace ANY DEFINED BY with the appropriate variable type element and the components constraint. Replace the element used in the constraint with the appropriate fixed type element and simple constraint.
  6. Add any simple constraints as appropriate.
  7. Define any objects and fill in elements for object sets as appropriate.

5. Security Considerations πŸ’€

⚠️ this part is seriously important, bestie 😭 when you downgrade a module from X.68x syntax to X.208, you lose the potential for automated enforcement of the constraints the module's author wrote πŸ₯Ί those constraints should be captured in prose or ASN.1 comments and enforced some other way, as needed πŸ”

depending on which features the ASN.1 compiler you're using supports, the code that enforces and uses constraints might get generated automatically, or the programmer might have to write it by hand πŸ§‘β€πŸ’» it is the programmer's job to make sure the constraints expressed in prose or in the ASN.1 module are actually enforced πŸ’― no skipping this one, periodt 🫑


6. References πŸ“š

6.1. Normative References ✨

okay bestie, these are the docs you need to have open before you touch anything πŸ“š they're the ones the spec leans on, no cap πŸ’…

[CCITT.X208.1988]  International Telephone and Telegraph Consultative
                   Committee, "Specification of Abstract Syntax
                   Notation One (ASN.1)", CCITT Recommendation X.208,
                   November 1988.

[CCITT.X680.2002]  International Telephone and Telegraph Consultative
                   Committee, "Abstract Syntax Notation One (ASN.1):
                   Specification of basic notation",
                   CCITT Recommendation X.680, July 2002.

[CCITT.X681.2002]  International Telephone and Telegraph Consultative
                   Committee, "Abstract Syntax Notation One (ASN.1):
                   Information object specification",
                   CCITT Recommendation X.681, July 2002.

[CCITT.X682.2002]  International Telephone and Telegraph Consultative
                   Committee, "Abstract Syntax Notation One (ASN.1):
                   Constraint specification", CCITT Recommendation
                   X.682, July 2002.

[CCITT.X683.2002]  International Telephone and Telegraph Consultative
                   Committee, "Abstract Syntax Notation One (ASN.1):
                   Parameterization of ASN.1 specifications",
                   CCITT Recommendation X.683, July 2002.

6.2. Informative References 🌸

these ones are the extra reading πŸ€“ helpful for context, not required to get the core spec working, but iconic for the deep dive energy 🫢

[CCITT.X209.1988]  International Telephone and Telegraph Consultative
                   Committee, "Specification of Basic Encoding Rules
                   for Abstract Syntax Notation One (ASN.1)",
                   CCITT Recommendation X.209, 1988.

[CCITT.X690.2002]  International Telephone and Telegraph Consultative
                   Committee, "ASN.1 encoding rules: Specification of
                   basic encoding Rules (BER), Canonical encoding
                   rules (CER) and Distinguished encoding rules
                   (DER)", CCITT Recommendation X.690, July 2002.

[RFC2560]          Myers, M., Ankney, R., Malpani, A., Galperin, S.,
                   and C. Adams, "X.509 Internet Public Key
                   Infrastructure Online Certificate Status Protocol
                   - OCSP", RFC 2560, June 1999.

[RFC5280]          Cooper, D., Santesson, S., Farrell, S., Boeyen,
                   S., Housley, R., and W. Polk, "Internet X.509
                   Public Key Infrastructure Certificate and
                   Certificate Revocation List (CRL) Profile",
                   RFC 5280, May 2008.

[RFC5652]          Housley, R., "Cryptographic Message Syntax (CMS)",
                   STD 70, RFC 5652, September 2009.

[RFC5911]          Hoffman, P. and J. Schaad, "New ASN.1 Modules for
                   Cryptographic Message Syntax (CMS) and S/MIME",
                   RFC 5911, June 2010.

[RFC5912]          Hoffman, P. and J. Schaad, "New ASN.1 Modules for
                   the Public Key Infrastructure Using X.509 (PKIX)",
                   RFC 5912, June 2010.

Authors' Addresses πŸ’œ

meet the people who wrote it πŸŽ€ if you have questions, these are your girls 🧚

Carl Wallace
Cygnacom Solutions
Suite 5400
7925 Jones Branch Drive
McLean, VA  22102

EMail: cwallace@cygnacom.com


Charles Gardiner
BBN Technologies
10 Moulton Street
Cambridge, MA  02138

EMail: gardiner@bbn.com

that's the whole doc, babe πŸ¦‹ you made it through the ASN.1 maze and honestly? iconic πŸ‘‘

πŸ“¦ where this page comes from