Skip to main content

Hybrid PQ/T Key Encapsulation Mechanisms
draft-irtf-cfrg-hybrid-kems-00

Document Type Active Internet-Draft (cfrg RG)
Author Deirdre Connolly
Last updated 2025-01-08
RFC stream Internet Research Task Force (IRTF)
Intended RFC status (None)
Formats
Additional resources Mailing list discussion
Stream IRTF state (None)
Consensus boilerplate Unknown
Document shepherd (None)
IESG IESG state I-D Exists
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-irtf-cfrg-hybrid-kems-00
Crypto Forum                                                 D. Connolly
Internet-Draft                                                 SandboxAQ
Intended status: Informational                            8 January 2025
Expires: 12 July 2025

                Hybrid PQ/T Key Encapsulation Mechanisms
                     draft-irtf-cfrg-hybrid-kems-00

Abstract

   This document defines generic techniques to achive hybrid post-
   quantum/traditional (PQ/T) key encapsulation mechanisms (KEMs) from
   post-quantum and traditional component algorithms that meet specified
   security properties.  It then uses those generic techniques to
   construct several concrete instances of hybrid KEMs.

Discussion Venues

   This note is to be removed before publishing as an RFC.

   Discussion of this document takes place on the Crypto Forum Research
   Group mailing list (cfrg@ietf.org), which is archived at
   https://mailarchive.ietf.org/arch/browse/cfrg.

   Source for this draft and an issue tracker can be found at
   https://github.com/cfrg/draft-irtf-cfrg-pq1.

Status of This Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current Internet-
   Drafts is at https://datatracker.ietf.org/drafts/current/.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   This Internet-Draft will expire on 12 July 2025.

Connolly                  Expires 12 July 2025                  [Page 1]
Internet-Draft                 hybrid-kems                  January 2025

Copyright Notice

   Copyright (c) 2025 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents (https://trustee.ietf.org/
   license-info) in effect on the date of publication of this document.
   Please review these documents carefully, as they describe your rights
   and restrictions with respect to this document.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   3
     1.1.  Motivation  . . . . . . . . . . . . . . . . . . . . . . .   4
   2.  Requirements Notation . . . . . . . . . . . . . . . . . . . .   4
   3.  Notation  . . . . . . . . . . . . . . . . . . . . . . . . . .   4
     3.1.  Key encapsulation mechanisms  . . . . . . . . . . . . . .   4
   4.  Hybrid KEM Security Properties  . . . . . . . . . . . . . . .   5
     4.1.  Hybrid Security . . . . . . . . . . . . . . . . . . . . .   5
     4.2.  IND-CCA security  . . . . . . . . . . . . . . . . . . . .   5
     4.3.  Ciphertext second preimage resistant (C2PRI) security /
           ciphertext collision resistance (CCR) . . . . . . . . . .   5
     4.4.  Binding properties  . . . . . . . . . . . . . . . . . . .   6
       4.4.1.  X-BIND-K-PK security  . . . . . . . . . . . . . . . .   6
       4.4.2.  X-BIND-K-CT security  . . . . . . . . . . . . . . . .   6
   5.  Cryptographic Dependencies  . . . . . . . . . . . . . . . . .   6
     5.1.  XOF . . . . . . . . . . . . . . . . . . . . . . . . . . .   6
     5.2.  Key Derivation Function KDF . . . . . . . . . . . . . . .   6
     5.3.  Post-Quantum KEM  . . . . . . . . . . . . . . . . . . . .   7
       5.3.1.  Post-quantum KEM ciphertext pq_CT . . . . . . . . . .   7
       5.3.2.  Post-quantum KEM public encapsulation key pq_PK . . .   7
       5.3.3.  Post-quantum KEM shared secret pq_SS  . . . . . . . .   7
       5.3.4.  Traditional KEM ciphertext trad_CT  . . . . . . . . .   7
       5.3.5.  Traditional KEM public encapsulation key trad_PK  . .   7
       5.3.6.  Traditional KEM shared secret trad_SS . . . . . . . .   7
     5.4.  Nominal Diffie-Hellman Group  . . . . . . . . . . . . . .   7
   6.  Other . . . . . . . . . . . . . . . . . . . . . . . . . . . .   9
     6.1.  label . . . . . . . . . . . . . . . . . . . . . . . . . .   9
   7.  Hybrid KEM Generic Constructions  . . . . . . . . . . . . . .   9
     7.1.  Common security requirements  . . . . . . . . . . . . . .   9
       7.1.1.  KDF as a secure PRF . . . . . . . . . . . . . . . . .   9
       7.1.2.  IND-CCA-secure Post-Quantum KEM . . . . . . . . . . .  10
       7.1.3.  IND-CCA-secure traditional KEM  . . . . . . . . . . .  10
       7.1.4.  Fixed lengths . . . . . . . . . . . . . . . . . . . .  10
     7.2.  Key Generation  . . . . . . . . . . . . . . . . . . . . .  10
     7.3.  'Kitchen Sink' construction:  . . . . . . . . . . . . . .  10
       7.3.1.  Security properties . . . . . . . . . . . . . . . . .  10

Connolly                  Expires 12 July 2025                  [Page 2]
Internet-Draft                 hybrid-kems                  January 2025

     7.4.  'QSF' construction  . . . . . . . . . . . . . . . . . . .  11
       7.4.1.  Requirements  . . . . . . . . . . . . . . . . . . . .  11
   8.  Concrete Hybrid KEM Instances . . . . . . . . . . . . . . . .  11
     8.1.  QSF-SHA3-256-ML-KEM-768-P-256 TODO: include the XOF?? . .  11
       8.1.1.  Key generation  . . . . . . . . . . . . . . . . . . .  13
     8.2.  Shared secret . . . . . . . . . . . . . . . . . . . . . .  13
     8.3.  Encapsulation . . . . . . . . . . . . . . . . . . . . . .  14
       8.3.1.  Derandomized  . . . . . . . . . . . . . . . . . . . .  14
     8.4.  Decapsulation . . . . . . . . . . . . . . . . . . . . . .  15
       8.4.1.  Security properties . . . . . . . . . . . . . . . . .  15
     8.5.  KitchenSink-HKDF-SHA-256-ML-KEM-768-X25519 TODO: include
            the XOF??  . . . . . . . . . . . . . . . . . . . . . . .  16
       8.5.1.  Key generation  . . . . . . . . . . . . . . . . . . .  17
     8.6.  Shared secret . . . . . . . . . . . . . . . . . . . . . .  18
     8.7.  Encapsulation . . . . . . . . . . . . . . . . . . . . . .  18
       8.7.1.  Derandomized  . . . . . . . . . . . . . . . . . . . .  19
     8.8.  Decapsulation . . . . . . . . . . . . . . . . . . . . . .  19
       8.8.1.  Security properties . . . . . . . . . . . . . . . . .  19
     8.9.  QSF-SHA3-256-ML-KEM-1024-P-384 TODO: include the XOF??  .  20
       8.9.1.  Key generation  . . . . . . . . . . . . . . . . . . .  21
     8.10. Shared secret . . . . . . . . . . . . . . . . . . . . . .  22
     8.11. Encapsulation . . . . . . . . . . . . . . . . . . . . . .  23
       8.11.1.  Derandomized . . . . . . . . . . . . . . . . . . . .  23
     8.12. Decapsulation . . . . . . . . . . . . . . . . . . . . . .  24
       8.12.1.  Security properties  . . . . . . . . . . . . . . . .  24
   9.  Random Scalar Generation  . . . . . . . . . . . . . . . . . .  25
     9.1.  Rejection Sampling  . . . . . . . . . . . . . . . . . . .  25
     9.2.  Wide Reduction  . . . . . . . . . . . . . . . . . . . . .  25
   10. Security Considerations . . . . . . . . . . . . . . . . . . .  25
     10.1.  Fixed-length . . . . . . . . . . . . . . . . . . . . . .  26
   11. Out of Scope  . . . . . . . . . . . . . . . . . . . . . . . .  26
     11.1.  More than two component KEMs . . . . . . . . . . . . . .  26
     11.2.  Parameterized output length  . . . . . . . . . . . . . .  26
     11.3.  Protocol-specific labels / info  . . . . . . . . . . . .  26
     11.4.  Other Component Primitives . . . . . . . . . . . . . . .  27
   12. IANA Considerations . . . . . . . . . . . . . . . . . . . . .  27
     12.1.  HPKE . . . . . . . . . . . . . . . . . . . . . . . . . .  27
   13. References  . . . . . . . . . . . . . . . . . . . . . . . . .  27
     13.1.  Normative References . . . . . . . . . . . . . . . . . .  27
     13.2.  Informative References . . . . . . . . . . . . . . . . .  27
   Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . .  29
   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . .  29

1.  Introduction

Connolly                  Expires 12 July 2025                  [Page 3]
Internet-Draft                 hybrid-kems                  January 2025

1.1.  Motivation

   There are many choices that can be made when specifying a hybrid KEM:
   the constituent KEMs; their security levels; the combiner; and the
   hash within, to name but a few.  Having too many similar options are
   a burden to the ecosystem.

   The aim of this document is provide a small set of techniques for
   constructing hybrid KEMs designed to achieve specific security
   properties given conforming component algorithms, that should be
   suitable for the vast majority of use cases.

2.  Requirements Notation

   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.

3.  Notation

   This document is consistent with all terminology defined in
   [I-D.driscoll-pqt-hybrid-terminology].

   The following terms are used throughout this document:

   *  random(n): return a pseudorandom byte string of length n bytes
      produced by a cryptographically-secure random number generator.

   *  concat(x0, ..., xN): Concatenation of byte strings.  concat(0x01,
      0x0203, 0x040506) = 0x010203040506.

   *  I2OSP(n, w): Convert non-negative integer n to a w-length, big-
      endian byte string, as described in [RFC8017].

   *  OS2IP(x): Convert byte string x to a non-negative integer, as
      described in [RFC8017], assuming big-endian byte order.

3.1.  Key encapsulation mechanisms

   Key encapsulation mechanisms (KEMs) are cryptographic schemes that
   consist of three algorithms:

   *  KeyGen() -> (pk, sk): A probabilistic key generation algorithm,
      which generates a public encapsulation key pk and a secret
      decapsulation key sk.

Connolly                  Expires 12 July 2025                  [Page 4]
Internet-Draft                 hybrid-kems                  January 2025

   *  Encaps(pk) -> (ct, shared_secret): A probabilistic encapsulation
      algorithm, which takes as input a public encapsulation key pk and
      outputs a ciphertext ct and shared secret shared_secret.

   *  Decaps(sk, ct) -> shared_secret: A decapsulation algorithm, which
      takes as input a secret decapsulation key sk and ciphertext ct and
      outputs a shared secret shared_secret.

4.  Hybrid KEM Security Properties

   Hybrid KEM constructions aim to provide security by combining two or
   more schemes so that security is preserved if all but one schemes are
   replaced by an arbitrarily bad scheme.

4.1.  Hybrid Security

   Informally, hybrid KEMs are secure if the KDF is secure, and if any
   one of the components KEMs is secure: this is the 'hybrid' property.

4.2.  IND-CCA security

   Also known as IND-CCA2 security for general public key encryption,
   for KEMs that encapsulate a new random 'message' each time.

   The notion of INDistinguishability against Chosen-Ciphertext Attacks
   (IND-CCA) [RS92] is now widely accepted as the standard security
   notion for asymmetric encryption schemes.  IND-CCA security requires
   that no efficient adversary can recognize which of two messages is
   encrypted in a given ciphertext, even if the two candidate messages
   are chosen by the adversary himself.

4.3.  Ciphertext second preimage resistant (C2PRI) security / ciphertext
      collision resistance (CCR)

   The notion where, even if a KEM has broken IND-CCA security (either
   due to construction, implementation, or other), its internal
   structure, based on the Fujisaki-Okamoto transform, guarantees that
   it is impossible to find a second ciphertext that decapsulates to the
   same shared secret K: this notion is known as ciphertext second
   preimage resistance (C2SPI) for KEMs [XWING].  The same notion has
   also been described as chosen ciphertext resistance elsewhere
   [CDM23].

Connolly                  Expires 12 July 2025                  [Page 5]
Internet-Draft                 hybrid-kems                  January 2025

4.4.  Binding properties

4.4.1.  X-BIND-K-PK security

4.4.2.  X-BIND-K-CT security

   Ciphertext second preimage resistance for KEMs ([C2PRI][XWING]).
   Related to the ciphertext collision-freeness of the underlying PKE
   scheme of a FO-transform KEM.  Also called ciphertext collision
   resistance.

5.  Cryptographic Dependencies

   The generic hybrid PQ/T KEM constructions we define depend on the the
   following cryptographic primitives:

   *  Extendable Output Function Section 5.1

   *  Key Derivation Function Section 5.2

   *  Post-Quantum-secure KEM Section 5.3

   *  Nominal Diffie-Hellman Group Section 5.4

5.1.  XOF

   Extendable-output function (XOF).  A function on bit strings in which
   the output can be extended to any desired length.  Ought to satisfy
   the following properties as long as the specified output length is
   sufficiently long to prevent trivial attacks:

   1.  (One-way) It is computationally infeasible to find any input that
       maps to any new pre-specified output.

   2.  (Collision-resistant) It is computationally infeasible to find
       any two distinct inputs that map to the same output.

   MUST provide the bit-security required to source input randomness for
   PQ/T components from a seed that is expanded to a output length, of
   which a subset is passed to the component key generation algorithms.

5.2.  Key Derivation Function KDF

   A secure key derivation function (KDF) that is modeled as a secure
   pseudorandom function (PRF) in the standard model [GHP2018] and
   independent random oracle in the random oracle model (ROM).

Connolly                  Expires 12 July 2025                  [Page 6]
Internet-Draft                 hybrid-kems                  January 2025

5.3.  Post-Quantum KEM

   An IND-CCA KEM that is resilient against post-quantum attacks.  It
   fulfills the scheme API in {kems}.

5.3.1.  Post-quantum KEM ciphertext pq_CT

   The ciphertext produced from one encapsulation from the post-quantum
   component KEM.

5.3.2.  Post-quantum KEM public encapsulation key pq_PK

   The public encapsulation key produced by one key generation from the
   post-quantum component KEM.

5.3.3.  Post-quantum KEM shared secret pq_SS

   The shared secret produced from one encapsulation/decapsulation from
   the post-quantum component KEM.

5.3.4.  Traditional KEM ciphertext trad_CT

   The ciphertext (or equivalent) produced from one encapsulation from
   the traditional component KEM.  For the constructions in this
   document, this is a Diffie-Hellman group element.

5.3.5.  Traditional KEM public encapsulation key trad_PK

   The public encapsulation key produced by one key generation from the
   traditional component KEM.  For the constructions in this document,
   this is a Diffie-Hellman group element.

5.3.6.  Traditional KEM shared secret trad_SS

   The shared secret produced from one encapsulation/decapsulation from
   the traditional component KEM.  For the constructions in this
   document, this is a Diffie-Hellman group element.

5.4.  Nominal Diffie-Hellman Group

   The traditional DH-KEM construction depends on an abelian group of
   order order.  We represent this group as the object G that
   additionally defines helper functions described below.  The group
   operation for G is addition + with identity element I.  For any
   elements A and B of the group G, A + B = B + A is also a member of G.
   Also, for any A in G, there exists an element -A such that A + (-A) =
   (-A) + A = I.  For convenience, we use - to denote subtraction, e.g.,
   A - B = A + (-B).  Integers, taken modulo the group order order, are

Connolly                  Expires 12 July 2025                  [Page 7]
Internet-Draft                 hybrid-kems                  January 2025

   called scalars; arithmetic operations on scalars are implicitly
   performed modulo order.  Scalar multiplication is equivalent to the
   repeated application of the group operation on an element A with
   itself r-1 times, denoted as ScalarMult(A, r).  We denote the sum,
   difference, and product of two scalars using the +, -, and *
   operators, respectively.  (Note that this means + may refer to group
   element addition or scalar addition, depending on the type of the
   operands.)  For any element A, ScalarMult(A, order) = I.  We denote B
   as a fixed generator of the group.  Scalar base multiplication is
   equivalent to the repeated application of the group operation on B
   with itself r-1 times, this is denoted as ScalarBaseMult(r).  The set
   of scalars corresponds to GF(order), which we refer to as the scalar
   field.  It is assumed that group element addition, negation, and
   equality comparison can be efficiently computed for arbitrary group
   elements.

   This document uses types Element and Scalar to denote elements of the
   group G and its set of scalars, respectively.  We denote Scalar(x) as
   the conversion of integer input x to the corresponding Scalar value
   with the same numeric value.  For example, Scalar(1) yields a Scalar
   representing the value 1.  We denote equality comparison of these
   types as == and assignment of values by =. When comparing Scalar
   values, e.g., for the purposes of sorting lists of Scalar values, the
   least nonnegative representation mod order is used.

   We now detail a number of member functions that can be invoked on G.

   *  Order(): Outputs the order of G (i.e., order).

   *  Identity(): Outputs the identity Element of the group (i.e., I).

   *  RandomScalar(): Outputs a random Scalar element in GF(order),
      i.e., a random scalar in [0, order - 1].

   *  ScalarMult(A, k): Outputs the scalar multiplication between
      Element A and Scalar k.

   *  ScalarBaseMult(k): Outputs the scalar multiplication between
      Scalar k and the group generator B.

   *  SerializeElement(A): Maps an Element A to a canonical byte array
      buf of fixed length Ne.  This function raises an error if A is the
      identity element of the group.

Connolly                  Expires 12 July 2025                  [Page 8]
Internet-Draft                 hybrid-kems                  January 2025

   *  DeserializeElement(buf): Attempts to map a byte array buf to an
      Element A, and fails if the input is not the valid canonical byte
      representation of an element of the group.  This function raises
      an error if deserialization fails or if A is the identity element
      of the group.

   *  SerializeScalar(s): Maps a Scalar s to a canonical byte array buf
      of fixed length Ns.

   *  DeserializeScalar(buf): Attempts to map a byte array buf to a
      Scalar s.  This function raises an error if deserialization fails.

6.  Other

6.1.  label

   ASCII-encoded bytes that provide oracle cloning [BDG2020] in the
   security game via domain separation.  The IND-CCA security of hybrid
   KEMs often relies on the KDF function KDF to behave as an independent
   random oracle, which the inclusion of the label achieves via domain
   separation [GHP2018].

   By design, the calls to KDF in these constructions and usage anywhere
   else in higher level protoocl use separate input domains unless
   intentionally duplicating the 'label' per concrete instance with
   fixed paramters.  This justifies modeling them as independent
   functions even if instantiated by the same KDF.  This domain
   separation is achieved by using prefix-free sets of label values.
   Recall that a set is prefix-free if no element is a prefix of another
   within the set.

   Length diffentiation is sometimes used to achieve domain separation
   but as a technique it is [brittle and prone to misuse][BDG2020] in
   practice so we favor the use of an explicit post-fix label.

7.  Hybrid KEM Generic Constructions

7.1.  Common security requirements

7.1.1.  KDF as a secure PRF

   A key derivation function (KDF) that is modeled as a secure
   pseudorandom function (PRF) in the standard model [GHP2018] and
   independent random oracle in the random oracle model (ROM).

Connolly                  Expires 12 July 2025                  [Page 9]
Internet-Draft                 hybrid-kems                  January 2025

7.1.2.  IND-CCA-secure Post-Quantum KEM

   A component post-quantum KEM that has IND-CCA security.

7.1.3.  IND-CCA-secure traditional KEM

   A component traditional KEM that has IND-CCA security.

7.1.4.  Fixed lengths

   Every instantiation in concrete parameters of the generic
   constructions is for fixed parameter sizes, KDF choice, and label,
   allowing the lengths to not also be encoded into the generic
   construction.  The label/KDF/component algorithm parameter sets MUST
   be disjoint and non-colliding.

   This document assumes and requires that the length of each public
   key, ciphertext, and shared secret is fixed once the algorithm is
   fixed in the concrete instantiations.  This is the case for all
   concrete instantiations in this document.

7.2.  Key Generation

   We specify a common generic key generation scheme for all generic
   constructions.  This requires the component key generation algorithns
   to accept the sufficient random seed, possibly according to their
   parameter set.

   ### Key derivation {#derive-key-pair}

7.3.  'Kitchen Sink' construction:

   As indicated by the name, the KitchenSink construction puts 'the
   whole transcript' through the KDF.  This relies on the minimum
   security properties of its component algorithms at the cost of more
   bytes needing to be processed by the KDF.

def KitchenSink-KEM.SharedSecret(pq_SS, trad_SS, pq_CT, pq_PK, trad_CT, trad_PK):
    return KDF(concat(pq_SS, trad_SS, pq_CT, pq_PK, trad_CT, trad_PK, label))

7.3.1.  Security properties

   Because the entire hybrid KEM ciphertext and encapsulation key
   material are included in the KDF preimage, the KitchenSink
   construction is resilient against implementation errors in the
   component algorithms.

Connolly                  Expires 12 July 2025                 [Page 10]
Internet-Draft                 hybrid-kems                  January 2025

7.4.  'QSF' construction

   Inspired by the generic QSF (Quantum Superiority Fighter) framework
   in [XWING], which leverages the security properties of a KEM like ML-
   KEM and an inlined instance of DH-KEM, to elide other public data
   like the PQ ciphertext and encapsulation key from the KDF input:

   def QSF-KEM.SharedSecret(pq_SS, trad_SS, trad_CT, trad_PK):
       return KDF(concat(pq_SS, trad_SS, trad_CT, trad_PK, label))

7.4.1.  Requirements

7.4.1.1.  Nominal Diffie-Hellman Group with strong Diffie-Hellman
          security

   A cryptographic group modelable as a nominal group where the strong
   Diffie-Hellman assumption holds {XWING}. Specically regarding a
   nominal group, this means that especially the QSF construction's
   security is based on a computational-Diffie-Hellman-like problem, but
   no assumption is made about the format of the generated group element
   - no assumption is made that the shared group element is
   indistinguishable from random bytes.

   The concrete instantiations in this document use elliptic curve
   groups that have been modeled as nominal groups in the literature.

7.4.1.2.  Post-quantum IND-CCA KEM with ciphertext second preimage
          resistance

   The QSF relies the post-quantum KEM component having IND-CCA security
   against a post-quantum attacker, and ciphertext second preimage
   resistance (C2SPI, also known as chosen ciphertext resistance, CCR).
   C2SPI/CCR is equivalent to LEAK-BIND-K,PK-CT security [CDM23]

7.4.1.3.  KDF is a secure (post-quantum) PRF, modelable as a random
          oracle

   Indistinguishability of the final shared secret from a random key is
   established by modeling the key-derivation function as a random
   oracle [XWING].

8.  Concrete Hybrid KEM Instances

8.1.  QSF-SHA3-256-ML-KEM-768-P-256

   Also known as [XWING] but with P-256 instead of X25519.

   *  label: QSF-SHA3-256-ML-KEM-768-P-256

Connolly                  Expires 12 July 2025                 [Page 11]
Internet-Draft                 hybrid-kems                  January 2025

   *  XOF: [SHAKE-256][FIPS202]

   *  KDF: [SHA3-256][FIPS202]

   *  PQ KEM: ML-KEM-768 [FIPS203]

   *  Group: [P-256][FIPS186] (secp256r1) [ANSIX9.62], where Ne = 33 and
      Ns = 32.

   This instantiation uses P-256 for the Group.

   *  Group: P-256

      -  Order(): Return 0xffffffff00000000ffffffffffffffffbce6faada7179
         e84f3b9cac2fc632551.

      -  Identity(): As defined in [ANSIX9.62].

      -  RandomScalar(): Implemented by returning a uniformly random
         Scalar in the range [0, G.Order() - 1].  Refer to Section 9 for
         implementation guidance.

      -  SerializeElement(A): Implemented using the compressed Elliptic-
         Curve-Point-to-Octet-String method according to [SEC1],
         yielding a 33-byte output.  Additionally, this function
         validates that the input element is not the group identity
         element.

      -  DeserializeElement(buf): Implemented by attempting to
         deserialize a 33-byte input string to a public key using the
         compressed Octet-String-to-Elliptic-Curve-Point method
         according to [SEC1], and then performs public-key validation as
         defined in section 3.2.2.1 of [SEC1].  This includes checking
         that the coordinates of the resulting point are in the correct
         range, that the point is on the curve, and that the point is
         not the point at infinity.  (As noted in the specification,
         validation of the point order is not required since the
         cofactor is 1.)  If any of these checks fail, deserialization
         returns an error.

      -  SerializeScalar(s): Implemented using the Field-Element-to-
         Octet-String conversion according to [SEC1].

      -  DeserializeScalar(buf): Implemented by attempting to
         deserialize a Scalar from a 32-byte string using Octet-String-
         to-Field-Element from [SEC1].  This function can fail if the
         input does not represent a Scalar in the range [0, G.Order() -
         1].

Connolly                  Expires 12 July 2025                 [Page 12]
Internet-Draft                 hybrid-kems                  January 2025

8.1.1.  Key generation

   A keypair (decapsulation key, encapsulation key) is generated as
   follows.

def expandDecapsulationKey(sk):
  expanded = SHAKE256(sk, 96)
  (pk_M, sk_M) = ML-KEM-768.KeyGen_internal(expanded[0:32], expanded[32:64])
  sk_G = Scalar(expanded[64:96])
  pk_G = ScalarMultBase(sk_G)
  return (sk_M, sk_G, pk_M, pk_G)

def GenerateKeyPair():
  sk = random(32)
  (sk_M, sk_G, pk_M, pk_G) = expandDecapsulationKey(sk)
  return sk, concat(pk_M, pk_G)

   GenerateKeyPair() returns the 32 byte secret decapsulation key sk and
   the 1217 byte encapsulation key pk.

   For testing, it is convenient to have a deterministic version of key
   generation.  An implementation MAY provide the following derandomized
   variant of key generation.

   def GenerateKeyPairDerand(sk):
     sk_M, sk_G, pk_M, pk_G = expandDecapsulationKey(sk)
     return sk, concat(pk_M, pk_X)

   sk MUST be 32 bytes.

   GenerateKeyPairDerand() returns the 32 byte secret decapsulation key
   sk and the 1217 byte encapsulation key pk.

8.2.  Shared secret

   Given 32-byte strings ss_M, ss_G, and the 33-byte strings ct_G, pk_G,
   representing the ML-KEM-768 shared secret, P-256 shared secret, P-256
   ciphertext (ephemeral public key) and P-256 public key respectively,
   the 32 byte combined shared secret is given by:

   def SharedSecret(ss_M, ss_G, ct_G, pk_G):
     return SHA3-256(concat(
       ss_M,
       ss_X,
       ct_G,
       pk_G,
       `label`
     ))

Connolly                  Expires 12 July 2025                 [Page 13]
Internet-Draft                 hybrid-kems                  January 2025

   where label is the instance label.  In hex label is given by TODO.

8.3.  Encapsulation

   Given an encapsulation key pk, encapsulation proceeds as follows.

   def Encapsulate(pk):
     pk_M = pk[0:1184]
     pk_G = pk[1184:1217]
     ek_G = RandomScalar()
     ct_G = ScalarMultBase(ek_G)
     ss_G = ScalarMult(ek_G, pk_G)
     (ss_M, ct_M) = ML-KEM-768.Encaps(pk_M)
     ss = SharedSecret(ss_M, ss_G, ct_G, pk_G)
     ct = concat(ct_M, ct_G)
     return (ss, ct)

   pk is a 1217 byte X-Wing encapsulation key resulting from
   GeneratePublicKey()

   Encapsulate() returns the 32 byte shared secret ss and the 1121 byte
   ciphertext ct.

   Note that Encapsulate() may raise an error if the ML-KEM
   encapsulation does not pass the check of [FIPS203] §7.2.

8.3.1.  Derandomized

   For testing, it is convenient to have a deterministic version of
   encapsulation.  An implementation MAY provide the following
   derandomized function.

   def EncapsulateDerand(pk, eseed):
     pk_M = pk[0:1184]
     pk_G = pk[1184:1217]
     ek_G = eseed[32:65]
     ct_G = ScalarMultBase(ek_G)
     ss_G = ScalarMult(ek_G, pk_G)

     (ss_M, ct_M) = ML-KEM-768.EncapsDerand(pk_M, eseed[0:32])
     ss = SharedSecret(ss_M, ss_G, ct_G, pk_G)
     ct = concat(ct_M, ct_G)
     return (ss, ct)

   pk is a 1217 byte X-Wing encapsulation key resulting from
   GeneratePublicKey() eseed MUST be 65 bytes.

Connolly                  Expires 12 July 2025                 [Page 14]
Internet-Draft                 hybrid-kems                  January 2025

   EncapsulateDerand() returns the 32 byte shared secret ss and the 1121
   byte ciphertext ct.

8.4.  Decapsulation

   def Decapsulate(ct, sk):
     (sk_M, sk_G, pk_M, pk_G) = expandDecapsulationKey(sk)
     ct_M = ct[0:1088]
     ct_G = ct[1088:1121]
     ss_M = ML-KEM-768.Decapsulate(ct_M, sk_M)
     ss_G = ScalarMult(sk_G, ct_G)
     return SharedSecret(ss_M, ss_G, ct_G, pk_G)

   ct is the 1121 byte ciphertext resulting from Encapsulate() sk is a
   32 byte decapsulation key resulting from GenerateKeyPair()

   Decapsulate() returns the 32 byte shared secret.

8.4.1.  Security properties

8.4.1.1.  Binding

   The inlined DH-KEM is instantiated over the elliptic curve group
   P-256: as shown in [CDM23], this gives the traditional KEM maximum
   binding properties (MAL-BIND-K-CT, MAL-BIND-K-PK).

   ML-KEM-768 as standardized in [FIPS203], when using the 64-byte seed
   key format as is here, provides MAL-BIND-K-CT security and LEAK-BIND-
   K-PK security, as demonstrated in [SCHMIEG2024].

   Therefore this concrete instance provides MAL-BIND-K-PK and MAL-BIND-
   K-CT security.

   This implies via [KSMW2024] that this instance also satisfies

   *  MAL-BIND-K,CT-PK

   *  MAL-BIND-K,PK-CT

   *  LEAK-BIND-K-PK

   *  LEAK-BIND-K-CT

   *  LEAK-BIND-K,CT-PK

   *  LEAK-BIND-K,PK-CT

   *  HON-BIND-K-PK

Connolly                  Expires 12 July 2025                 [Page 15]
Internet-Draft                 hybrid-kems                  January 2025

   *  HON-BIND-K-CT

   *  HON-BIND-K,CT-PK

   *  HON-BIND-K,PK-CT

8.5.  KitchenSink-HKDF-SHA-256-ML-KEM-768-X25519

   *  label: KitchenSink-HKDF-SHA-256-ML-KEM-768-X25519

   *  XOF: [SHAKE-256][FIPS202]

   *  KDF: HKDF-SHA-256 [HKDF]

   HKDF is comprised of HKDF-Extract and HKDF-Expand.  We compose them
   as one function here:

   def LabeledExtract(salt, label, ikm):
     labeled_ikm = concat("Hybrid", suite_id, label, ikm)
     return HDKF-Extract(salt, labeled_ikm)

   def LabeledExpand(prk, label, info, L):
     labeled_info = concat(I2OSP(L, 2), "Hybrid", suite_id,
                           label, info)
     return HKDF-Expand(prk, labeled_info, L)

   def HKDF(preimage):
     prk = LabeledExtract("", "hybrid_prk", preimage)
     shared_secret = LabeledExpand(prk, "shared_secret", "", 32)
     return shared_secret

   *  PQ KEM: ML-KEM-768 [FIPS203]

   *  Group: X25519 [X25519]

   This instantiation uses X25519 for the Group.

   *  Group: Curve25519 [X25519], where Ne = 32 and Ns = 32.

      -  Order(): Return 2^252 + 0x14def9dea2f79cd65812631a5cf5d3ed (see
         [RFC7748]).

      -  Identity(): As defined in [RFC7748].

Connolly                  Expires 12 July 2025                 [Page 16]
Internet-Draft                 hybrid-kems                  January 2025

      -  RandomScalar(): Implemented by returning a uniformly random
         Scalar in the range [0, G.Order() - 1].  Refer to Section 9 for
         implementation guidance.

      -  SerializeElement(A): Implemented as specified in [RFC7748].

      -  DeserializeElement(buf): Implemented as specified in [RFC7748].

      -  SerializeScalar(s): Implemented by outputting the little-endian
         32-byte encoding of the Scalar value with the top three bits
         set to zero.

      -  DeserializeScalar(buf): Implemented by attempting to
         deserialize a Scalar from a little-endian 32-byte string.  This
         function can fail if the input does not represent a Scalar in
         the range [0, G.Order() - 1].  Note that this means the top
         three bits of the input MUST be zero.

8.5.1.  Key generation

   A keypair (decapsulation key, encapsulation key) is generated as
   follows.

def expandDecapsulationKey(sk):
  expanded = SHAKE256(sk, 96)
  (pk_M, sk_M) = ML-KEM-768.KeyGen_internal(expanded[0:32], expanded[32:64])
  sk_G = Scalar(expanded[64:96])
  pk_G = ScalarMultBase(sk_G)
  return (sk_M, sk_G, pk_M, pk_G)

def GenerateKeyPair():
  sk = random(32)
  (sk_M, sk_G, pk_M, pk_G) = expandDecapsulationKey(sk)
  return sk, concat(pk_M, pk_G)

   GenerateKeyPair() returns the 32 byte secret decapsulation key sk and
   the 1216 byte encapsulation key pk.

   For testing, it is convenient to have a deterministic version of key
   generation.  An implementation MAY provide the following derandomized
   variant of key generation.

   def GenerateKeyPairDerand(sk):
     sk_M, sk_G, pk_M, pk_G = expandDecapsulationKey(sk)
     return sk, concat(pk_M, pk_X)

   sk MUST be 32 bytes.

Connolly                  Expires 12 July 2025                 [Page 17]
Internet-Draft                 hybrid-kems                  January 2025

   GenerateKeyPairDerand() returns the 32 byte secret encapsulation key
   sk and the 1216 byte decapsulation key pk.

8.6.  Shared secret

   Given 32-byte strings ss_M, ss_G, ct_G, pk_G, representing the ML-
   KEM-768 shared secret, X25519 shared secret, X25519 ciphertext
   (ephemeral public key) and X25519 public key respectively, the 32
   byte combined shared secret is given by:

   def SharedSecret(ss_M, ss_G, ct_G, pk_G):
     return HKDF(concat(
       ss_M,
       ss_X,
       ct_G,
       pk_G,
       `label`
     ))

   where label is the instance label.  In hex label is given by TODO.

8.7.  Encapsulation

   Given an encapsulation key pk, encapsulation proceeds as follows.

   def Encapsulate(pk):
     pk_M = pk[0:1184]
     pk_G = pk[1184:1216]
     ek_G = RandomScalar()
     ct_G = ScalarMultBase(ek_G)
     ss_G = ScalarMult(ek_G, pk_G)
     (ss_M, ct_M) = ML-KEM-768.Encaps(pk_M)
     ss = SharedSecret(ss_M, ss_G, ct_G, pk_G)
     ct = concat(ct_M, ct_G)
     return (ss, ct)

   pk is a 1216 byte encapsulation key resulting from
   GeneratePublicKey()

   Encapsulate() returns the 32 byte shared secret ss and the 1120 byte
   ciphertext ct.

   Note that Encapsulate() may raise an error if the ML-KEM
   encapsulation does not pass the check of [FIPS203] §7.2.

Connolly                  Expires 12 July 2025                 [Page 18]
Internet-Draft                 hybrid-kems                  January 2025

8.7.1.  Derandomized

   For testing, it is convenient to have a deterministic version of
   encapsulation.  An implementation MAY provide the following
   derandomized function.

   def EncapsulateDerand(pk, eseed):
     pk_M = pk[0:1184]
     pk_G = pk[1184:1216]
     ek_G = eseed[32:64]
     ct_G = ScalarMultBase(ek_G)
     ss_G = ScalarMult(ek_G, pk_G)

     (ss_M, ct_M) = ML-KEM-768.EncapsDerand(pk_M, eseed[0:32])
     ss = SharedSecret(ss_M, ss_G, ct_G, pk_G)
     ct = concat(ct_M, ct_G)
     return (ss, ct)

   pk is a 1217 byte X-Wing encapsulation key resulting from
   GeneratePublicKey() eseed MUST be 65 bytes.

   EncapsulateDerand() returns the 32 byte shared secret ss and the 1121
   byte ciphertext ct.

8.8.  Decapsulation

   def Decapsulate(ct, sk):
     (sk_M, sk_G, pk_M, pk_G) = expandDecapsulationKey(sk)
     ct_M = ct[0:1088]
     ct_G = ct[1088:1120]
     ss_M = ML-KEM-768.Decapsulate(ct_M, sk_M)
     ss_G = ScalarMult(sk_G, ct_G)
     return SharedSecret(ss_M, ss_G, ct_G, pk_G)

   ct is the 1120 byte ciphertext resulting from Encapsulate() sk is a
   32 byte decapsulation key resulting from GenerateKeyPair()

   Decapsulate() returns the 32 byte shared secret.

8.8.1.  Security properties

8.8.1.1.  Binding

   The inlined DH-KEM instantiated over the elliptic curve group X25519:
   as shown in [CDM23], this gives the traditional KEM maximum binding
   properties (MAL-BIND-K-CT, MAL-BIND-K-PK).

Connolly                  Expires 12 July 2025                 [Page 19]
Internet-Draft                 hybrid-kems                  January 2025

   ML-KEM-768 as standardized in [FIPS203], when using the 64-byte seed
   key format as is here, provides MAL-BIND-K-CT security and LEAK-BIND-
   K-PK security, as demonstrated in [SCHMIEG2024].  Further, the ML-KEM
   ciphertext and encapsulation key are included in the KDF preimage,
   giving straightforward CT and PK binding for the entire bytes of the
   hybrid KEM ciphertext and encapsulation key.  Therefore this concrete
   instance provides MAL-BIND-K-PK and MAL-BIND-K-CT security.

   This implies via [KSMW2024] that this instance also satisfies

   *  MAL-BIND-K,CT-PK

   *  MAL-BIND-K,PK-CT

   *  LEAK-BIND-K-PK

   *  LEAK-BIND-K-CT

   *  LEAK-BIND-K,CT-PK

   *  LEAK-BIND-K,PK-CT

   *  HON-BIND-K-PK

   *  HON-BIND-K-CT

   *  HON-BIND-K,CT-PK

   *  HON-BIND-K,PK-CT

8.9.  QSF-SHA3-256-ML-KEM-1024-P-384

   *  label: QSF-SHA3-256-ML-KEM-768-P-256

   *  XOF: [SHAKE-256][FIPS202]

   *  KDF: [SHA3-256][FIPS202]

   *  PQ KEM: ML-KEM-1024 [FIPS203]

   *  Group: [P-384][FIPS186] (secp256r1) [ANSIX9.62], where Ne = 33 and
      Ns = 32.

   This instantiation uses P-384 for the Group.

   *  Group: P-384

Connolly                  Expires 12 July 2025                 [Page 20]
Internet-Draft                 hybrid-kems                  January 2025

      -  Order(): Return 0xfffffffffffffffffffffffffffffffffffffffffffff
         fffc7634d81f4372ddf 581a0db248b0a77aecec196accc52973

      -  Identity(): As defined in [ANSIX9.62].

      -  RandomScalar(): Implemented by returning a uniformly random
         Scalar in the range [0, G.Order() - 1].  Refer to Section 9 for
         implementation guidance.

      -  SerializeElement(A): Implemented using the compressed Elliptic-
         Curve-Point-to-Octet-String method according to [SEC1],
         yielding a 61-byte output.  Additionally, this function
         validates that the input element is not the group identity
         element.

      -  DeserializeElement(buf): Implemented by attempting to
         deserialize a 61-byte input string to a public key using the
         compressed Octet-String-to-Elliptic-Curve-Point method
         according to [SEC1], and then performs public-key validation as
         defined in section 3.2.2.1 of [SEC1].  This includes checking
         that the coordinates of the resulting point are in the correct
         range, that the point is on the curve, and that the point is
         not the point at infinity.  (As noted in the specification,
         validation of the point order is not required since the
         cofactor is 1.)  If any of these checks fail, deserialization
         returns an error.

      -  SerializeScalar(s): Implemented using the Field-Element-to-
         Octet-String conversion according to [SEC1].

      -  DeserializeScalar(buf): Implemented by attempting to
         deserialize a Scalar from a 48-byte string using Octet-String-
         to-Field-Element from [SEC1].  This function can fail if the
         input does not represent a Scalar in the range [0, G.Order() -
         1].

8.9.1.  Key generation

   A keypair (decapsulation key, encapsulation key) is generated as
   follows.

Connolly                  Expires 12 July 2025                 [Page 21]
Internet-Draft                 hybrid-kems                  January 2025

def expandDecapsulationKey(sk):
  expanded = SHAKE256(sk, 112)
  (pk_M, sk_M) = ML-KEM-1024.KeyGen_internal(expanded[0:32], expanded[32:64])
  sk_G = Scalar(expanded[64:112])
  pk_G = ScalarMultBase(sk_G)
  return (sk_M, sk_G, pk_M, pk_G)

def GenerateKeyPair():
  sk = random(32)
  (sk_M, sk_G, pk_M, pk_G) = expandDecapsulationKey(sk)
  return sk, concat(pk_M, pk_G)

   GenerateKeyPair() returns the 32 byte secret decapsulation key sk and
   the 1629 byte encapsulation key pk.

   For testing, it is convenient to have a deterministic version of key
   generation.  An implementation MAY provide the following derandomized
   variant of key generation.

   def GenerateKeyPairDerand(sk):
     sk_M, sk_G, pk_M, pk_G = expandDecapsulationKey(sk)
     return sk, concat(pk_M, pk_X)

   sk MUST be 32 bytes.

   GenerateKeyPairDerand() returns the 32 byte secret decapsulation key
   sk and the 1629 byte encapsulation key pk.

8.10.  Shared secret

   Given 32-byte string ss_M, the 61-byte strings ss_G, ct_G, pk_G,
   representing the ML-KEM-1024 shared secret, P-384 shared secret,
   P-384 ciphertext (ephemeral public key) and P-384 public key
   respectively, the 32 byte combined shared secret is given by:

   def SharedSecret(ss_M, ss_G, ct_G, pk_G):
     return SHA3-256(concat(
       ss_M,
       ss_X,
       ct_G,
       pk_G,
       `label`
     ))

   where label is the instance label.  In hex label is given by TODO.

Connolly                  Expires 12 July 2025                 [Page 22]
Internet-Draft                 hybrid-kems                  January 2025

8.11.  Encapsulation

   Given an encapsulation key pk, encapsulation proceeds as follows.

   def Encapsulate(pk):
     pk_M = pk[0:1568]
     pk_G = pk[1568:1629]
     ek_G = RandomScalar()
     ct_G = ScalarMultBase(ek_G)
     ss_G = ScalarMult(ek_G, pk_G)
     (ss_M, ct_M) = ML-KEM-1024.Encaps(pk_M)
     ss = SharedSecret(ss_M, ss_G, ct_G, pk_G)
     ct = concat(ct_M, ct_G)
     return (ss, ct)

   pk is a 1629 byte X-Wing encapsulation key resulting from
   GeneratePublicKey()

   Encapsulate() returns the 32 byte shared secret ss and the 1629 byte
   ciphertext ct.

   Note that Encapsulate() may raise an error if the ML-KEM
   encapsulation does not pass the check of [FIPS203] §7.2.

8.11.1.  Derandomized

   For testing, it is convenient to have a deterministic version of
   encapsulation.  An implementation MAY provide the following
   derandomized function.

   def EncapsulateDerand(pk, eseed):
     pk_M = pk[0:1568]
     pk_G = pk[1568:1629]
     ek_G = eseed[32:80]
     ct_G = ScalarMultBase(ek_G)
     ss_G = ScalarMult(ek_G, pk_G)

     (ss_M, ct_M) = ML-KEM-768.EncapsDerand(pk_M, eseed[0:32])
     ss = SharedSecret(ss_M, ss_G, ct_G, pk_G)
     ct = concat(ct_M, ct_G)
     return (ss, ct)

   pk is a 1629 byte X-Wing encapsulation key resulting from
   GeneratePublicKey() eseed MUST be 80 bytes.

   EncapsulateDerand() returns the 32 byte shared secret ss and the 1629
   byte ciphertext ct.

Connolly                  Expires 12 July 2025                 [Page 23]
Internet-Draft                 hybrid-kems                  January 2025

8.12.  Decapsulation

   def Decapsulate(ct, sk):
     (sk_M, sk_G, pk_M, pk_G) = expandDecapsulationKey(sk)
     ct_M = ct[0:1568]
     ct_G = ct[1568:1629]
     ss_M = ML-KEM-1024.Decapsulate(ct_M, sk_M)
     ss_G = ScalarMult(sk_G, ct_G)
     return SharedSecret(ss_M, ss_G, ct_G, pk_G)

   ct is the 1629 byte ciphertext resulting from Encapsulate() sk is a
   32 byte decapsulation key resulting from GenerateKeyPair()

   Decapsulate() returns the 32 byte shared secret.

8.12.1.  Security properties

8.12.1.1.  Binding

   The inlined DH-KEM is instantiated over the elliptic curve group
   P-384: as shown in [CDM23], this gives the traditional KEM maximum
   binding properties (MAL-BIND-K-CT, MAL-BIND-K-PK).

   ML-KEM-1024 as standardized in [FIPS203], when using the 64-byte seed
   key format as is here, provides MAL-BIND-K-CT security and LEAK-BIND-
   K-PK security, as demonstrated in [SCHMIEG2024].

   Therefore this concrete instance provides MAL-BIND-K-PK and MAL-BIND-
   K-CT security.

   This implies via [KSMW2024] that this instance also satisfies

   *  MAL-BIND-K,CT-PK

   *  MAL-BIND-K,PK-CT

   *  LEAK-BIND-K-PK

   *  LEAK-BIND-K-CT

   *  LEAK-BIND-K,CT-PK

   *  LEAK-BIND-K,PK-CT

   *  HON-BIND-K-PK

   *  HON-BIND-K-CT

Connolly                  Expires 12 July 2025                 [Page 24]
Internet-Draft                 hybrid-kems                  January 2025

   *  HON-BIND-K,CT-PK

   *  HON-BIND-K,PK-CT

9.  Random Scalar Generation

   Two popular algorithms for generating a random integer uniformly
   distributed in the range [0, G.Order() -1] are as follows:

9.1.  Rejection Sampling

   Generate a random byte array with Ns bytes, and attempt to map to a
   Scalar by calling DeserializeScalar in constant time.  If it
   succeeds, return the result.  If it fails, try again with another
   random byte array, until the procedure succeeds.  Failure to
   implement DeserializeScalar in constant time can leak information
   about the underlying corresponding Scalar.

   As an optimization, if the group order is very close to a power of 2,
   it is acceptable to omit the rejection test completely.  In
   particular, if the group order is p, and there is an integer b such
   that |p - 2^b| is less than 2^(b/2), then RandomScalar can simply
   return a uniformly random integer of at most b bits.

9.2.  Wide Reduction

   Generate a random byte array with l = ceil(((3 *
   ceil(log2(G.Order()))) / 2) / 8) bytes, and interpret it as an
   integer; reduce the integer modulo G.Order() and return the result.
   See Section 5 of [HASH-TO-CURVE] for the underlying derivation of l.

10.  Security Considerations

   Informally, these hybrid KEMs are secure if the KDF is secure, and
   either the elliptic curve is secure, or the post-quantum KEM is
   secure: this is the 'hybrid' property.

   More precisely for the concrete instantiations in this document, if
   SHA3-256, SHA3-512, and SHAKE-256 may be modelled as a random oracle,
   then the IND-CCA security of QSF constructions is bounded by the IND-
   CCA security of ML-KEM, and the gap-CDH security of secp256n1, see
   [XWING].

Connolly                  Expires 12 July 2025                 [Page 25]
Internet-Draft                 hybrid-kems                  January 2025

10.1.  Fixed-length

   Variable-length secrets are generally dangerous.  In particular,
   using key material of variable length and processing it using hash
   functions may result in a timing side channel.  In broad terms, when
   the secret is longer, the hash function may need to process more
   blocks internally.  In some unfortunate circumstances, this has led
   to timing attacks, e.g. the Lucky Thirteen [LUCKY13] and Raccoon
   [RACCOON] attacks.

   Furthermore, [AVIRAM] identified a risk of using variable-length
   secrets when the hash function used in the key derivation function is
   no longer collision-resistant.

   If concatenation were to be used with values that are not fixed-
   length, a length prefix or other unambiguous encoding would need to
   be used to ensure that the composition of the two values is injective
   and requires a mechanism different from that specified in this
   document.

   Therefore, this specification MUST only be used with algorithms which
   have fixed-length shared secrets (after the variant has been fixed by
   the algorithm identifier in the NamedGroup negotiation in
   Section 3.1).

11.  Out of Scope

   Considerations that were considered and not included in these
   designs:

11.1.  More than two component KEMs

   Design team decided to restrict the space to only two components, a
   traditional and a post-quantum KEM.

11.2.  Parameterized output length

   Not analyzed as part of any security proofs in the literature, and a
   complicatation deemed unnecessary.

11.3.  Protocol-specific labels / info

   The concrete instantiations have specific labels, protocol-specific
   information is out of scope.

Connolly                  Expires 12 July 2025                 [Page 26]
Internet-Draft                 hybrid-kems                  January 2025

11.4.  Other Component Primitives

   There is demand for other hybrid variants that either use different
   primitives (RSA, NTRU, Classic McEliece, FrodoKEM), parameters, or
   that use a combiner optimized for a specific use case.  Other use
   cases could be covered in subsequent documents and not included here.

12.  IANA Considerations

12.1.  HPKE

   TODO

13.  References

13.1.  Normative References

   [FIPS203]  "Module-lattice-based key-encapsulation mechanism
              standard", National Institute of Standards and Technology
              (U.S.), DOI 10.6028/nist.fips.203, August 2024,
              <https://doi.org/10.6028/nist.fips.203>.

   [HASH-TO-CURVE]
              Faz-Hernandez, A., Scott, S., Sullivan, N., Wahby, R. S.,
              and C. A. Wood, "Hashing to Elliptic Curves", RFC 9380,
              DOI 10.17487/RFC9380, August 2023,
              <https://www.rfc-editor.org/rfc/rfc9380>.

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119,
              DOI 10.17487/RFC2119, March 1997,
              <https://www.rfc-editor.org/rfc/rfc2119>.

   [RFC7748]  Langley, A., Hamburg, M., and S. Turner, "Elliptic Curves
              for Security", RFC 7748, DOI 10.17487/RFC7748, January
              2016, <https://www.rfc-editor.org/rfc/rfc7748>.

   [RFC8017]  Moriarty, K., Ed., Kaliski, B., Jonsson, J., and A. Rusch,
              "PKCS #1: RSA Cryptography Specifications Version 2.2",
              RFC 8017, DOI 10.17487/RFC8017, November 2016,
              <https://www.rfc-editor.org/rfc/rfc8017>.

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
              2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
              May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.

13.2.  Informative References

Connolly                  Expires 12 July 2025                 [Page 27]
Internet-Draft                 hybrid-kems                  January 2025

   [ANSIX9.62]
              ANS, "Public Key Cryptography for the Financial Services
              Industry: the Elliptic Curve Digital Signature Algorithm
              (ECDSA)", ANS X9.62-2005, November 2005.

   [AVIRAM]   Nimrod Aviram, Benjamin Dowling, Ilan Komargodski, Kenny
              Paterson, Eyal Ronen, and Eylon Yogev, "[TLS] Combining
              Secrets in Hybrid Key Exchange in TLS 1.3", 1 September
              2021, <https://mailarchive.ietf.org/arch/msg/tls/
              F4SVeL2xbGPaPB2GW_GkBbD_a5M/>.

   [BDG2020]  "Separate Your Domains: NIST PQC KEMs, Oracle Cloning and
              Read-Only Indifferentiability", 2020,
              <https://eprint.iacr.org/2020/241.pdf>.

   [CDM23]    Cremers, C., Dax, A., and N. Medinger, "Keeping Up with
              the KEMs: Stronger Security Notions for KEMs and automated
              analysis of KEM-based protocols", 2023,
              <https://eprint.iacr.org/2023/1933.pdf>.

   [FIPS186]  "Digital Signature Standard (DSS)", National Institute of
              Standards and Technology (U.S.),
              DOI 10.6028/nist.fips.186-5, February 2023,
              <https://doi.org/10.6028/nist.fips.186-5>.

   [GHP2018]  "KEM Combiners", 2018,
              <https://eprint.iacr.org/2018/024.pdf>.

   [HKDF]     Krawczyk, H. and P. Eronen, "HMAC-based Extract-and-Expand
              Key Derivation Function (HKDF)", RFC 5869,
              DOI 10.17487/RFC5869, May 2010,
              <https://www.rfc-editor.org/rfc/rfc5869>.

   [I-D.driscoll-pqt-hybrid-terminology]
              D, F., "Terminology for Post-Quantum Traditional Hybrid
              Schemes", Work in Progress, Internet-Draft, draft-
              driscoll-pqt-hybrid-terminology-02, 7 March 2023,
              <https://datatracker.ietf.org/doc/html/draft-driscoll-pqt-
              hybrid-terminology-02>.

   [KSMW2024] Kraemer, J., Struck, P., and M. Weishaupl, "Binding
              Security of Implicitly-Rejecting KEMs and Application to
              BIKE and HQC", n.d., <https://eprint.iacr.org/2024/1233>.

   [LUCKY13]  Al Fardan, N. J. and K. G. Paterson, "Lucky Thirteen:
              Breaking the TLS and DTLS record protocols", n.d.,
              <https://ieeexplore.ieee.org/
              iel7/6547086/6547088/06547131.pdf>.

Connolly                  Expires 12 July 2025                 [Page 28]
Internet-Draft                 hybrid-kems                  January 2025

   [RACCOON]  Merget, R., Brinkmann, M., Aviram, N., Somorovsky, J.,
              Mittmann, J., and J. Schwenk, "Raccoon Attack: Finding and
              Exploiting Most-Significant-Bit-Oracles in TLS-DH(E)",
              September 2020, <https://raccoon-attack.com/>.

   [SCHMIEG2024]
              Schmieg, S., "Unbindable Kemmy Schmidt: ML-KEM is neither
              MAL-BIND-K-CT nor MAL-BIND-K-PK", 2024,
              <https://eprint.iacr.org/2024/523.pdf>.

   [SEC1]     "Elliptic Curve Cryptography, Standards for Efficient
              Cryptography Group, ver. 2", 2009,
              <https://secg.org/sec1-v2.pdf>.

   [X25519]   Langley, A., Hamburg, M., and S. Turner, "Elliptic Curves
              for Security", RFC 7748, DOI 10.17487/RFC7748, January
              2016, <https://www.rfc-editor.org/rfc/rfc7748>.

   [XWING]    "X-Wing: The Hybrid KEM You’ve Been Looking For", 2024,
              <https://eprint.iacr.org/2024/039.pdf>.

Acknowledgments

   TODO acknowledge.

Author's Address

   Deirdre Connolly
   SandboxAQ
   Email: durumcrustulum@gmail.com

Connolly                  Expires 12 July 2025                 [Page 29]