Use of the SLH-DSA Signature Algorithm in the Cryptographic Message Syntax (CMS)
RFC 0000
Russ Housley
Vigil Security, LLC
housley@vigilsec.com
Scott Fluhrer
Cisco Systems
sfluhrer@cisco.com
Panos Kampanakis
Amazon Web Services
kpanos@amazon.com
Bas Westerbaan
Cloudflare
bas@westerbaan.name
January 2025
SEC
lamps
example
SLH-DSA is a stateless hash-based signature scheme. This document specifies the conventions for using the SLH-DSA signature algorithm with the Cryptographic Message Syntax (CMS). In addition, the algorithm identifier and public key syntax are provided.
Introduction
This document specifies the conventions for using the SLH-DSA hash-based signature algorithm [FIPS205] with the Cryptographic Message Syntax (CMS) [RFC5652] signed-data content type.
SLH-DSA offers two signature modes: pure mode and pre-hash mode. SLH-DSA signature operations include a context string as input. The context string has a maximum length of 255 bytes. By default, the context string is the empty string. This document only specifies the use of pure mode with an empty context string for the CMS signed-data content type.
SLH-DSA offers three security levels. The parameters for each of the security levels were chosen to provide 128 bits of security, 192 bits of security, and 256 bits of security. Separate algorithm identifiers have been assigned for SLH-DSA at each of these security levels.
SLH-DSA is a stateless hash-based signature algorithm. Other hash-based signature algorithms are stateful, including HSS/LMS [RFC8554] and XMSS [RFC8391]. Without the need for state kept by the signer, SLH-DSA is much less fragile than the stateful hash-based signature algorithms.
ASN.1
CMS values are generated using ASN.1 [X680], using the Basic Encoding Rules (BER) and the Distinguished Encoding Rules (DER) [X690].
Motivation
There have been recent advances in cryptanalysis and advances in the development of quantum computers. Each of these advances pose a threat to widely deployed digital signature algorithms.
If cryptographically relevant quantum computers (CRQC) are ever built, they will be able to break many of the public-key cryptosystems currently in use, including RSA, DSA, ECDSA, and EdDSA. A post-quantum cryptosystem (PQC) is secure against quantum computers that have more than a trivial number of quantum bits (qu-bits). It is open to conjecture when it will be feasible to build such quantum computers; however, it is prudent to use cryptographic algorithms that remain secure if a CRQC is invented. SLH-DSA is a PQC signature algorithm.
Terminology
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
SLH-DSA Hash-based Signature Algorithm Overview
SLH-DSA is a hash-based signature scheme. SLH-DSA makes use of a few time signature construction, namely Forest of Random Subsets (FORS) and a hypertree. FORS signs a message with a private key. The corresponding FORS public keys are the leaves in k binary trees. The roots of these trees are hashed together to form a FORS root. SLH-DSA uses a one-time signature scheme called WOTS+. The FORS tree roots are signed by a WOTS+ one-time signature private key. The corresponding WOTS+ public keys form the leaves in d-layers of Merkle subtrees in the SLH-DSA hypertree. The bottom layer of that hypertree signs the FORS roots with WOTS+. The root of the bottom Merkle subtrees are then signed with WOTS+ and the corresponding WOTS+ public keys form the leaves of the next level up subtree. Subtree roots are consequently signed by their corresponding subtree layers until the top subtree is reached. The top layer subtree forms the hypertree root which is trusted at the verifier.
A SLH-DSA signature consists of the randomization string, the FORS signature, the WOTS+ signature in each layer, and the path to the root of each subtree until the root of the hypertree is reached.
A SLH-DSA signature is verified by verifying the FORS signature, the WOTS+ signatures and the path to the root of each subtree. When reaching the root of the hypertree, the signature verifies only if it hashes to the pre-trusted root of the SLH-DSA hypertree.
SLH-DSA is a stateless hash-based signature algorithm. Stateful hash-based signature schemes require that the WOTS+ private key (generated by using a state index) is never reused or the scheme loses it security. Although its security decreases, FORS which is used at the bottom of the SLH-DSA hypertree does not collapse if the same private key used to sign two or more different messages like in stateful hash-based signature schemes. Without the need for state kept by the signer to ensure it is not reused, SLH-DSA is much less fragile.
SLH-DSA was designed to sign up to 2^64 messages and offers three security levels. The parameters of the SLH-DSA hypertree include the security parameter, the hash function, the tree height, the number of layers of subtrees, the Winternitz parameter of WOTS+, the number of FORS trees and leaves in each. The parameters for each of the security levels were chosen to at least as secure as a generic block cipher of 128, 192, or 256 bits.
SLH-DSA Public Key Identifier
The AlgorithmIdentifier for a SLH-DSA public key MUST use one of the twelve id-slh-dsa object identifiers listed below, based on the security level used to generate the SLH-DSA hypertree, the small or fast version of the algorithm, and the use of SHA2 [FIPS180] or SHAKE [FIPS202]. For example, id-slh-dsa-shake-256s represents the 256-bit security level, the small version of the algorithm, and the use of SHAKE256. The parameters field of the AlgorithmIdentifier for the SLH-DSA public key MUST be absent.

   nistAlgorithms OBJECT IDENTIFIER ::= { joint-iso-itu-t(2)
     country(16) us(840) organization(1) gov(101) csor(3) 4 }

   sigAlgs OBJECT IDENTIFIER ::= { nistAlgorithms 3 }

   id-slh-dsa-sha2-128s OBJECT IDENTIFIER ::= { sigAlgs 20 }

   id-slh-dsa-sha2-128f OBJECT IDENTIFIER ::= { sigAlgs 21 }

   id-slh-dsa-sha2-192s OBJECT IDENTIFIER ::= { sigAlgs 22 }

   id-slh-dsa-sha2-192f OBJECT IDENTIFIER ::= { sigAlgs 23 }

   id-slh-dsa-sha2-256s OBJECT IDENTIFIER ::= { sigAlgs 24 }

   id-slh-dsa-sha2-256f OBJECT IDENTIFIER ::= { sigAlgs 25 }

   id-slh-dsa-shake-128s OBJECT IDENTIFIER ::= { sigAlgs 26 }

   id-slh-dsa-shake-128f OBJECT IDENTIFIER ::= { sigAlgs 27 }

   id-slh-dsa-shake-192s OBJECT IDENTIFIER ::= { sigAlgs 28 }

   id-slh-dsa-shake-192f OBJECT IDENTIFIER ::= { sigAlgs 29 }

   id-slh-dsa-shake-256s OBJECT IDENTIFIER ::= { sigAlgs 30 }

   id-slh-dsa-shake-256f OBJECT IDENTIFIER ::= { sigAlgs 31 }

When this AlgorithmIdentifier appears in the SubjectPublicKeyInfo field of an X.509 certificate [RFC5280], the certificate key usage extension MAY contain digitalSignature, nonRepudiation, keyCertSign, and cRLSign; the certificate key usage extension MUST NOT contain other values.

   pk-slh-dsa-sha2-128s PUBLIC-KEY ::= {
       IDENTIFIER id-slh-dsa-sha2-128s
       -- KEY no ASN.1 wrapping --
       CERT-KEY-USAGE
         { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
       -- PRIVATE-KEY no ASN.1 wrapping -- }

   pk-slh-dsa-sha2-128f PUBLIC-KEY ::= {
       IDENTIFIER id-slh-dsa-sha2-128f
       -- KEY no ASN.1 wrapping --
       CERT-KEY-USAGE
         { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
       -- PRIVATE-KEY no ASN.1 wrapping -- }

   pk-slh-dsa-sha2-192s PUBLIC-KEY ::= {
       IDENTIFIER id-slh-dsa-sha2-192s
       -- KEY no ASN.1 wrapping --
       CERT-KEY-USAGE
         { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
       -- PRIVATE-KEY no ASN.1 wrapping -- }

   pk-slh-dsa-sha2-192f PUBLIC-KEY ::= {
       IDENTIFIER id-slh-dsa-sha2-192f
       -- KEY no ASN.1 wrapping --
       CERT-KEY-USAGE
         { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
       -- PRIVATE-KEY no ASN.1 wrapping -- }

   pk-slh-dsa-sha2-256s PUBLIC-KEY ::= {
       IDENTIFIER id-slh-dsa-sha2-256s
       -- KEY no ASN.1 wrapping --
       CERT-KEY-USAGE
         { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
       -- PRIVATE-KEY no ASN.1 wrapping -- }

   pk-slh-dsa-sha2-256f PUBLIC-KEY ::= {
       IDENTIFIER id-slh-dsa-sha2-256f
       -- KEY no ASN.1 wrapping --
       CERT-KEY-USAGE
         { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
       -- PRIVATE-KEY no ASN.1 wrapping -- }

   pk-slh-dsa-shake-128s PUBLIC-KEY ::= {
       IDENTIFIER id-slh-dsa-shake-128s
       -- KEY no ASN.1 wrapping --
       CERT-KEY-USAGE
         { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
       -- PRIVATE-KEY no ASN.1 wrapping -- }

   pk-slh-dsa-shake-128f PUBLIC-KEY ::= {
       IDENTIFIER id-slh-dsa-shake-128f
       -- KEY no ASN.1 wrapping --
       CERT-KEY-USAGE
         { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
       -- PRIVATE-KEY no ASN.1 wrapping -- }

   pk-slh-dsa-shake-192s PUBLIC-KEY ::= {
       IDENTIFIER id-slh-dsa-shake-192s
       -- KEY no ASN.1 wrapping --
       CERT-KEY-USAGE
         { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
       -- PRIVATE-KEY no ASN.1 wrapping -- }

   pk-slh-dsa-shake-192f PUBLIC-KEY ::= {
       IDENTIFIER id-slh-dsa-shake-192f
       -- KEY no ASN.1 wrapping --
       CERT-KEY-USAGE
         { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
       -- PRIVATE-KEY no ASN.1 wrapping -- }

   pk-slh-dsa-shake-256s PUBLIC-KEY ::= {
       IDENTIFIER id-slh-dsa-shake-256s
       -- KEY no ASN.1 wrapping --
       CERT-KEY-USAGE
         { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
       -- PRIVATE-KEY no ASN.1 wrapping -- }

   pk-slh-dsa-shake-256f PUBLIC-KEY ::= {
       IDENTIFIER id-slh-dsa-shake-256f
       -- KEY no ASN.1 wrapping --
       CERT-KEY-USAGE
         { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
       -- PRIVATE-KEY no ASN.1 wrapping -- }

   SLH-DSA-PublicKey ::= OCTET STRING (SIZE (32 | 48 | 64))

   SLH-DSA-PrivateKey ::= OCTET STRING (SIZE (64 | 96 | 128))

No additional encoding of the SLH-DSA public key is applied in the SubjectPublicKeyInfo field of an X.509 certificate [RFC5280].
No additional encoding of the SLH-DSA private key is applied in the PrivateKeyInfo field of the privateKey field of the OneAsymmetricKey type of an Asymmetric Key Package [RFC5958].
When a SLH-DSA public key appears outside of a SubjectPublicKeyInfo type in an environment that uses ASN.1 encoding, the SLH-DSA public key can be encoded as an OCTET STRING by using the SLH-DSA-PublicKey type.
When a SLH-DSA private key appears outside of an Asymmetric Key Package in an environment that uses ASN.1 encoding, the SLH-DSA private key can be encoded as an OCTET STRING by using the SLH-DSA-PrivateKey type.
Signed-data Conventions
As specified in CMS [RFC5652], the digital signature is produced from the message digest and the signer's private key. The signature is computed over different values depending on whether signed attributes are absent or present.
When signed attributes are absent, the SLH-DSA (pure mode) signature is computed over the content. When signed attributes are present, a hash MUST be computed over the content using the same hash function that is used in the SLH-DSA tree. The signed attributes MUST include a content-type attribute and a message-digest attribute. The message-digest attribute contains the hash value of the content. The SLH-DSA signature is computed over the DER encoding of the set of signed attributes. The SLH-DSA signature generation operation is called slh_sign; see Section 10.2.1 of [FIPS205]. In summary:

   IF (signed attributes are absent)
   THEN slh_sign(content)
   ELSE message-digest attribute = Hash(content);
        slh_sign(DER(SignedAttributes))

In some implementations, performance may be significantly improved by signing and verifying DER(SignedAttributes) when the content is large. That is, passing an entire large message content to the signing function or the signature validation function can have an impact on performance. When the signed attributes are present, Section 5.3 of [RFC5652] requires the inclusion of the content-type attribute and the message-digest attribute. Other attributes can also be included.
When using SLH-DSA and signed attributes are present in the SignerInfo, the digestAlgorithms field in the SignedData MUST include the identifier for the one-way hash function used to compute the message digest.
When using SLH-DSA, the fields in the SignerInfo are used as follows:
digestAlgorithm:
The digestAlgorithm MUST identify a one-way hash function. When signed attributes are absent, the digestAlgorithm identifier MUST match the hash function used in the SLH-DSA tree (as shown in the list below). When signed attributes are present, to ensure collision resistance, the identified hash function MUST produce a hash value that is at least twice the size of the hash function used in the SLH-DSA tree. The hash functions defined in [FIPS180] and [FIPS202] MUST be supported for use with the variants of SLH-DSA as shown below:

      id-slh-dsa-sha2-128s:  SHA-256
      id-slh-dsa-sha2-128f:  SHA-256
      id-slh-dsa-sha2-192s:  SHA-512
      id-slh-dsa-sha2-192f:  SHA-512
      id-slh-dsa-sha2-256s:  SHA-512
      id-slh-dsa-sha2-256f:  SHA-512
      id-slh-dsa-shake-128s: SHAKE128 with 256 bit output
      id-slh-dsa-shake-128f: SHAKE128 with 256 bit output
      id-slh-dsa-shake-192s: SHAKE256 with 512 bit output
      id-slh-dsa-shake-192f: SHAKE256 with 512 bit output
      id-slh-dsa-shake-256s: SHAKE256 with 512 bit output
      id-slh-dsa-shake-256f: SHAKE256 with 512 bit output

The object identifiers for SHA-256 and SHA-512 are included in [RFC5754]. The object identifiers for SHAKE128 and SHAKE256 are included in [RFC8702]. In all four cases, the AlgorithmIdentifier SHOULD NOT include parameters.
signatureAlgorithm:
The signatureAlgorithm MUST contain one of the the SLH-DSA algorithm identifiers, and the algorithm parameters field MUST be absent. The algorithm identifier MUST be one of the following:

      id-slh-dsa-sha2-128s,  id-slh-dsa-sha2-128f,
      id-slh-dsa-sha2-192s,  id-slh-dsa-sha2-192f,
      id-slh-dsa-sha2-256s,  id-slh-dsa-sha2-256f,
      id-slh-dsa-shake-128s, id-slh-dsa-shake-128f,
      id-slh-dsa-shake-192s, id-slh-dsa-shake-192f,
      id-slh-dsa-shake-256s, id-slh-dsa-shake-256f.

signature:
The signature contains the signature value resulting from the SLH-DSA signing operation with the parameters associated with the selected signatureAlgorithm. The SLH-DSA signature generation operation is specified in Section 10.2.1 of [FIPS205], and the SLH-DSA signature verification operation is specified in Section 10.3 of [FIPS205]. Signature verification MUST include checking that the signatureAlgorithm field identifies SLH-DSA parameters that are consistent with public key used to validate the signature.
Security Considerations
Implementations MUST protect the private keys. Compromise of the private keys may result in the ability to forge signatures.
When generating an SLH-DSA key pair, an implementation MUST generate each key pair independently of all other key pairs in the SLH-DSA hypertree.
A SLH-DSA tree MUST NOT be used for more than 2^64 signing operations.
The generation of private keys relies on random numbers. The use of inadequate pseudo-random number generators (PRNGs) to generate these values can result in little or no security. An attacker may find it much easier to reproduce the PRNG environment that produced the keys, searching the resulting small set of possibilities, rather than brute force searching the whole key space. The generation of quality random numbers is difficult, and [RFC4086] offers important guidance in this area.
To avoid algorithm substitution attacks, the CMSAlgorithmProtection attribute defined in [RFC6211] SHOULD be included in signed attributes.
Implementers should consider their particular use cases and may choose to implement optional fault attack countermeasures [CMP2018] [Ge2023]. Verifying a signature before releasing the signature value is a typical fault attack countermeasure; however, this countermeasure is not effective for SLH-DSA [Ge2023]. Redundancy by replicating the signature generation process MAY be used as an effective fault attack countermeasure for SLH-DSA [Ge2023]; however, the SLH-DSA signature generation is already considered slow.
Likewise, Implementers should consider their particular use cases and may choose to implement protections against passive power and emissions side-channel attacks [SLotH].
Operational Considerations
If slh_sign is implemented in a hardware device such as hardware security module (HSM) or portable cryptographic token, implementations can avoid sending the full content to the device. By including signed attributes, which necessarily include the message-digest attribute and the content-type attribute as described in Section 5.3 of [RFC5652], the much smaller set of signed attributes are sent to the device for signing.
By including signed attributes in the SignerInfo, one can obtain similar interface characteristics to SLH-DSA in pre-hash mode. With pre-hash mode, the hash of the content is passed to the SLH-DSA signature operation instead of the full message content. By including signed attributes in the SignerInfo, a relatively small to-be-signed value is passed to the SLH-DSA signature operation. For this reason, SLH-DSA pre-hash mode is not specified for use with the CMS SignedData. Note SLH-DSA pre-hash mode always yields a different signature value than SLH-DSA pure mode, even if the to-be-signed content is the same.
When using SLH-DSA in pure mode, it is not possible to single-pass process the content to verify a SignedData message that does not contain signed attributes. To assist recipients that might make use of stream-based APIs, implementers SHOULD include signed attributes within any SignerInfo that uses SLH-DSA as signature algorithm. Doing so allows the recipient implementation to avoid keeping the signed content in memory. Recall that when signed attributes are present, they MUST contain a content-type attribute and a message-digest attribute, and they SHOULD contain a CMSAlgorithmProtection attribute.
IANA Considerations
For the ASN.1 Module in the Appendix of this document, IANA is requested to assign an object identifier (OID) for the module identifier (TBD1) with a Description of "id-mod-slh-dsa-2024". The OID for the module should be allocated in the "SMI Security for S/MIME Module Identifier" (1.2.840.113549.1.9.16.0).
References
Normative References
[FIPS180]

Secure Hash Standard (SHS)
National Institute of Standards and Technology (NIST)
August 2015
FIPS PUB 180-4
[FIPS202]

SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions
National Institute of Standards and Technology (NIST)
August 2015
FIPS PUB 202
[FIPS205]

Stateless Hash-Based Digital Signature Standard
National Institute of Standards and Technology (NIST)
13 August 2024
FIPS PUB 205
[X680]

Information technology -- Abstract Syntax Notation One (ASN.1): Specification of basic notation
ITU-T
February 2021
ITU-T Recommendation X.680
ISO/IEC 8824-1:2021
[X690]

Information technology -- ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)
ITU-T
February 2021
ITU-T Recommendation X.690
ISO/IEC 8825-1-2021
Informative References
[CMP2018]

Grafting Trees: A Fault Attack Against the SPHINCS Framework
Laurent Castelnovi
Ange Martinelli
Thomas Prest
2018
Post-Quantum Cryptography pp. 165-184
PQCrypto 2018
Lecture Notes in Computer Science vol 10786
[SLotH]

Accelerating SLH-DSA by Two Orders of Magnitude with a Single Hash Unit
M-J. Saarinen
2024
[Ge2023]

On Protecting SPHINCS+ Against Fault Attacks
Aymeric Genêt
2023
TCHES 2023/02
DOI 10.46586/tches.v2023.i2.80-114
[RFC5652]
[RFC8554]
[RFC8391]
[RFC2119]
[RFC8174]
[RFC5280]
[RFC5958]
[RFC4086]
[RFC6211]
[RFC5911]
ASN.1 Module
This ASN.1 Module builds upon the conventions established in [RFC5911].

SLH-DSA-Module-2024
  { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
    id-smime(16) id-mod(0) id-mod-slh-dsa-2024(TBD1) }

DEFINITIONS IMPLICIT TAGS ::= BEGIN

EXPORTS ALL;

IMPORTS
  PUBLIC-KEY, SIGNATURE-ALGORITHM, SMIME-CAPS
    FROM AlgorithmInformation-2009  -- in [RFC5911]
    { iso(1) identified-organization(3) dod(6) internet(1)
      security(5) mechanisms(5) pkix(7) id-mod(0)
      id-mod-algorithmInformation-02(58) } ;

--
-- Object Identifiers
--

nistAlgorithms OBJECT IDENTIFIER ::= { joint-iso-itu-t(2)
  country(16) us(840) organization(1) gov(101) csor(3) 4 }

sigAlgs OBJECT IDENTIFIER ::= { nistAlgorithms 3 }

id-slh-dsa-sha2-128s OBJECT IDENTIFIER ::= { sigAlgs 20 }

id-slh-dsa-sha2-128f OBJECT IDENTIFIER ::= { sigAlgs 21 }

id-slh-dsa-sha2-192s OBJECT IDENTIFIER ::= { sigAlgs 22 }

id-slh-dsa-sha2-192f OBJECT IDENTIFIER ::= { sigAlgs 23 }

id-slh-dsa-sha2-256s OBJECT IDENTIFIER ::= { sigAlgs 24 }

id-slh-dsa-sha2-256f OBJECT IDENTIFIER ::= { sigAlgs 25 }

id-slh-dsa-shake-128s OBJECT IDENTIFIER ::= { sigAlgs 26 }

id-slh-dsa-shake-128f OBJECT IDENTIFIER ::= { sigAlgs 27 }

id-slh-dsa-shake-192s OBJECT IDENTIFIER ::= { sigAlgs 28 }

id-slh-dsa-shake-192f OBJECT IDENTIFIER ::= { sigAlgs 29 }

id-slh-dsa-shake-256s OBJECT IDENTIFIER ::= { sigAlgs 30 }

id-slh-dsa-shake-256f OBJECT IDENTIFIER ::= { sigAlgs 31 }

--
-- Signature Algorithm, Public Key, and Private Key
--

sa-slh-dsa-sha2-128s SIGNATURE-ALGORITHM ::= {
    IDENTIFIER id-slh-dsa-sha2-128s
    PARAMS ARE absent
    PUBLIC-KEYS { pk-slh-dsa-sha2-128s }
    SMIME-CAPS { IDENTIFIED BY id-slh-dsa-sha2-128s } }

sa-slh-dsa-sha2-128f SIGNATURE-ALGORITHM ::= {
    IDENTIFIER id-slh-dsa-sha2-128f
    PARAMS ARE absent
    PUBLIC-KEYS { pk-slh-dsa-sha2-128f }
    SMIME-CAPS { IDENTIFIED BY id-slh-dsa-sha2-128f } }

sa-slh-dsa-sha2-192s SIGNATURE-ALGORITHM ::= {
    IDENTIFIER id-slh-dsa-sha2-192s
    PARAMS ARE absent
    PUBLIC-KEYS { pk-slh-dsa-sha2-192s }
    SMIME-CAPS { IDENTIFIED BY id-slh-dsa-sha2-192s } }

sa-slh-dsa-sha2-192f SIGNATURE-ALGORITHM ::= {
    IDENTIFIER id-slh-dsa-sha2-192f
    PARAMS ARE absent
    PUBLIC-KEYS { pk-slh-dsa-sha2-192f }
    SMIME-CAPS { IDENTIFIED BY id-slh-dsa-sha2-192f } }

sa-slh-dsa-sha2-256s SIGNATURE-ALGORITHM ::= {
    IDENTIFIER id-slh-dsa-sha2-256s
    PARAMS ARE absent
    PUBLIC-KEYS { pk-slh-dsa-sha2-256s }
    SMIME-CAPS { IDENTIFIED BY id-slh-dsa-sha2-256s } }

sa-slh-dsa-sha2-256f SIGNATURE-ALGORITHM ::= {
    IDENTIFIER id-slh-dsa-sha2-256f
    PARAMS ARE absent
    PUBLIC-KEYS { pk-slh-dsa-sha2-256f }
    SMIME-CAPS { IDENTIFIED BY id-slh-dsa-sha2-256f } }

sa-slh-dsa-shake-128s SIGNATURE-ALGORITHM ::= {
    IDENTIFIER id-slh-dsa-shake-128s
    PARAMS ARE absent
    PUBLIC-KEYS { pk-slh-dsa-shake-128s }
    SMIME-CAPS { IDENTIFIED BY id-slh-dsa-shake-128s } }

sa-slh-dsa-shake-128f SIGNATURE-ALGORITHM ::= {
    IDENTIFIER id-slh-dsa-shake-128f
    PARAMS ARE absent
    PUBLIC-KEYS { pk-slh-dsa-shake-128f }
    SMIME-CAPS { IDENTIFIED BY id-slh-dsa-shake-128f } }

sa-slh-dsa-shake-192s SIGNATURE-ALGORITHM ::= {
    IDENTIFIER id-slh-dsa-shake-192s
    PARAMS ARE absent
    PUBLIC-KEYS { pk-slh-dsa-shake-192s }
    SMIME-CAPS { IDENTIFIED BY id-slh-dsa-shake-192s } }

sa-slh-dsa-shake-192f SIGNATURE-ALGORITHM ::= {
    IDENTIFIER id-slh-dsa-shake-192f
    PARAMS ARE absent
    PUBLIC-KEYS { pk-slh-dsa-shake-192f }
    SMIME-CAPS { IDENTIFIED BY id-slh-dsa-shake-192f } }

sa-slh-dsa-shake-256s SIGNATURE-ALGORITHM ::= {
    IDENTIFIER id-slh-dsa-shake-256s
    PARAMS ARE absent
    PUBLIC-KEYS { pk-slh-dsa-shake-256s }
    SMIME-CAPS { IDENTIFIED BY id-slh-dsa-shake-256s } }

sa-slh-dsa-shake-256f SIGNATURE-ALGORITHM ::= {
    IDENTIFIER id-slh-dsa-shake-256f
    PARAMS ARE absent
    PUBLIC-KEYS { pk-slh-dsa-shake-256f }
    SMIME-CAPS { IDENTIFIED BY id-slh-dsa-shake-256f } }

pk-slh-dsa-sha2-128s PUBLIC-KEY ::= {
    IDENTIFIER id-slh-dsa-sha2-128s
    -- KEY no ASN.1 wrapping --
    CERT-KEY-USAGE
      { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
    -- PRIVATE-KEY no ASN.1 wrapping -- }

pk-slh-dsa-sha2-128f PUBLIC-KEY ::= {
    IDENTIFIER id-slh-dsa-sha2-128f
    -- KEY no ASN.1 wrapping --
    CERT-KEY-USAGE
      { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
    -- PRIVATE-KEY no ASN.1 wrapping -- }

pk-slh-dsa-sha2-192s PUBLIC-KEY ::= {
    IDENTIFIER id-slh-dsa-sha2-192s
    -- KEY no ASN.1 wrapping --
    CERT-KEY-USAGE
      { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
    -- PRIVATE-KEY no ASN.1 wrapping -- }

pk-slh-dsa-sha2-192f PUBLIC-KEY ::= {
    IDENTIFIER id-slh-dsa-sha2-192f
    -- KEY no ASN.1 wrapping --
    CERT-KEY-USAGE
      { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
    -- PRIVATE-KEY no ASN.1 wrapping -- }

pk-slh-dsa-sha2-256s PUBLIC-KEY ::= {
    IDENTIFIER id-slh-dsa-sha2-256s
    -- KEY no ASN.1 wrapping --
    CERT-KEY-USAGE
      { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
    -- PRIVATE-KEY no ASN.1 wrapping -- }

pk-slh-dsa-sha2-256f PUBLIC-KEY ::= {
    IDENTIFIER id-slh-dsa-sha2-256f
    -- KEY no ASN.1 wrapping --
    CERT-KEY-USAGE
      { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
    -- PRIVATE-KEY no ASN.1 wrapping -- }

pk-slh-dsa-shake-128s PUBLIC-KEY ::= {
    IDENTIFIER id-slh-dsa-shake-128s
    -- KEY no ASN.1 wrapping --
    CERT-KEY-USAGE
      { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
    -- PRIVATE-KEY no ASN.1 wrapping -- }

pk-slh-dsa-shake-128f PUBLIC-KEY ::= {
    IDENTIFIER id-slh-dsa-shake-128f
    -- KEY no ASN.1 wrapping --
    CERT-KEY-USAGE
      { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
    -- PRIVATE-KEY no ASN.1 wrapping -- }

pk-slh-dsa-shake-192s PUBLIC-KEY ::= {
    IDENTIFIER id-slh-dsa-shake-192s
    -- KEY no ASN.1 wrapping --
    CERT-KEY-USAGE
      { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
    -- PRIVATE-KEY no ASN.1 wrapping -- }

pk-slh-dsa-shake-192f PUBLIC-KEY ::= {
    IDENTIFIER id-slh-dsa-shake-192f
    -- KEY no ASN.1 wrapping --
    CERT-KEY-USAGE
      { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
    -- PRIVATE-KEY no ASN.1 wrapping -- }

pk-slh-dsa-shake-256s PUBLIC-KEY ::= {
    IDENTIFIER id-slh-dsa-shake-256s
    -- KEY no ASN.1 wrapping --
    CERT-KEY-USAGE
      { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
    -- PRIVATE-KEY no ASN.1 wrapping -- }

pk-slh-dsa-shake-256f PUBLIC-KEY ::= {
    IDENTIFIER id-slh-dsa-shake-256f
    -- KEY no ASN.1 wrapping --
    CERT-KEY-USAGE
      { digitalSignature, nonRepudiation, keyCertSign, cRLSign }
    -- PRIVATE-KEY no ASN.1 wrapping -- }

SLH-DSA-PublicKey ::= OCTET STRING (SIZE (32 | 48 | 64))

SLH-DSA-PrivateKey ::= OCTET STRING (SIZE (64 | 96 | 128))

--
-- Expand the signature algorithm set used by CMS [RFC5911]
--

SignatureAlgorithmSet SIGNATURE-ALGORITHM ::=
    { sa-slh-dsa-sha2-128s |
      sa-slh-dsa-sha2-128f |
      sa-slh-dsa-sha2-192s |
      sa-slh-dsa-sha2-192f |
      sa-slh-dsa-sha2-256s |
      sa-slh-dsa-sha2-256f |
      sa-slh-dsa-shake-128s |
      sa-slh-dsa-shake-128f |
      sa-slh-dsa-shake-192s |
      sa-slh-dsa-shake-192f |
      sa-slh-dsa-shake-256s |
      sa-slh-dsa-shake-256f,
      ... }

--
-- Expand the S/MIME capabilities set used by CMS [RFC5911]
--

SMimeCaps SMIME-CAPS ::=
    { sa-slh-dsa-sha2-128s.&smimeCaps |
      sa-slh-dsa-sha2-128f.&smimeCaps |
      sa-slh-dsa-sha2-192s.&smimeCaps |
      sa-slh-dsa-sha2-192f.&smimeCaps |
      sa-slh-dsa-sha2-256s.&smimeCaps |
      sa-slh-dsa-sha2-256f.&smimeCaps |
      sa-slh-dsa-shake-128s.&smimeCaps |
      sa-slh-dsa-shake-128f.&smimeCaps |
      sa-slh-dsa-shake-192s.&smimeCaps |
      sa-slh-dsa-shake-192f.&smimeCaps |
      sa-slh-dsa-shake-256s.&smimeCaps |
      sa-slh-dsa-shake-256f.&smimeCaps,
      ... }

END

Acknowledgements
Thanks to Mike Ounsworth, Tomas Gustavsson, Daniel Van Geest, Carl Wallace, Phillip Hallam-Baker, Dieter Bratko, Vijay Gurbani, Paul Wouters, and Roman Danyliw for their careful review and constructive comments.