From 2d6cd9871f69fb5d46d475864174990925bab469 Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Thu, 5 Sep 2024 14:18:35 +0200 Subject: [PATCH] kem: add X25519MLKEM768 TLS hybrid KEM --- kem/hybrid/hybrid.go | 21 ++++++++++++++++----- kem/schemes/schemes.go | 1 + kem/schemes/schemes_test.go | 1 + 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/kem/hybrid/hybrid.go b/kem/hybrid/hybrid.go index be8251c7f..8be85d70c 100644 --- a/kem/hybrid/hybrid.go +++ b/kem/hybrid/hybrid.go @@ -1,13 +1,13 @@ -// Package hybrid defines several hybrid classical/quantum KEMs. +// Package hybrid defines several hybrid classical/quantum KEMs for use in TLS. // -// KEMs are combined by simple concatenation of shared secrets, cipher texts, -// public keys, etc, see +// Hybrid KEMs in TLS are created by simple concatenation +// of shared secrets, cipher texts, public keys, etc. +// This is safe for TLS, see eg. // // https://datatracker.ietf.org/doc/draft-ietf-tls-hybrid-design/ // https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr2.pdf // -// Note that this is only fine if the shared secret is used in its entirety -// in a next step, such as being hashed or used as key. +// Note that this approach is not proven secure in broader context. // // For deriving a KEM keypair deterministically and encapsulating // deterministically, we expand a single seed to both using SHAKE256, @@ -38,6 +38,7 @@ import ( "github.com/cloudflare/circl/kem/kyber/kyber1024" "github.com/cloudflare/circl/kem/kyber/kyber512" "github.com/cloudflare/circl/kem/kyber/kyber768" + "github.com/cloudflare/circl/kem/mlkem/mlkem768" ) var ErrUninitialized = errors.New("public or private key not initialized") @@ -57,6 +58,10 @@ func Kyber1024X448() kem.Scheme { return kyber1024X } // Returns the hybrid KEM of Kyber768Draft00 and P-256. func P256Kyber768Draft00() kem.Scheme { return p256Kyber768Draft00 } +// Returns the hybrid KEM of ML-KEM-768 and X25519. +// https://www.ietf.org/archive/id/draft-kwiatkowski-tls-ecdhe-mlkem-01.html +func X25519MLKEM768() kem.Scheme { return xmlkem768 } + var p256Kyber768Draft00 kem.Scheme = &scheme{ "P256Kyber768Draft00", p256Kem, @@ -87,6 +92,12 @@ var kyber1024X kem.Scheme = &scheme{ kyber1024.Scheme(), } +var xmlkem768 kem.Scheme = &scheme{ + "X25519MLKEM768", + mlkem768.Scheme(), + x25519Kem, +} + // Public key of a hybrid KEM. type publicKey struct { scheme *scheme diff --git a/kem/schemes/schemes.go b/kem/schemes/schemes.go index da5f9839e..747d99e9d 100644 --- a/kem/schemes/schemes.go +++ b/kem/schemes/schemes.go @@ -49,6 +49,7 @@ var allSchemes = [...]kem.Scheme{ hybrid.Kyber768X448(), hybrid.Kyber1024X448(), hybrid.P256Kyber768Draft00(), + hybrid.X25519MLKEM768(), } var allSchemeNames map[string]kem.Scheme diff --git a/kem/schemes/schemes_test.go b/kem/schemes/schemes_test.go index be4c18a54..88a02f31b 100644 --- a/kem/schemes/schemes_test.go +++ b/kem/schemes/schemes_test.go @@ -163,4 +163,5 @@ func Example_schemes() { // Kyber768-X448 // Kyber1024-X448 // P256Kyber768Draft00 + // X25519MLKEM768 }