EVP_PKEY-MLX-KEM(7ssl)
π EVP_PKEY-MLX-KEM, EVP_KEYMGMT-MLX-KEM
okay so this is page EVP_PKEY-MLX-KEM(7ssl) from the OpenSSL crew, and bestie, it's about hybrid ML-KEM key support for TLS 1.3. post-quantum era, we're preparing. let's go π¦
β¨ NAME β¨
EVP_PKEY-MLX-KEM, EVP_KEYMGMT-MLX-KEM β hybrid ML-KEM key support for TLS 1.3. that's the whole vibe. π
πΈ DESCRIPTION πΈ
These hybrid ML_KEM algorithms derive the session secret from both an ECDH (classical) algorithm (think X25519, or P-256) and a post-quantum algorithm (ML_KEM). the point is that key agreement stays secure unless both schemes get broken. double security, no cap. π«Ά
real talk tho: the algorithms supported here are specifically for TLS 1.3 and are not suitable for other purposes. there is no encoder/decoder support, andEVP_PKEY_CTX_new_id()is also not supported, because there are no associatedEVP_PKEYtype identifiers. so don't try it, it's giving unsupported. π
The following names can be used by EVP_PKEY_CTX_new_from_name() using OpenSSL's default and FIPS providers:
X25519MLKEM768β the shared secret is the concatenation of a 32 byteEVP_PKEY-ML-KEM(7)shared secret followed by a 32 byteEVP_PKEY-X25519(7)shared secret. so like, ML-KEM first, X25519 second, in that order. note that X25519 is not an approved FIPS algorithm, but this combination is still allowed by FIPS 140-3 since ML-KEM is FIPS approved. iconic loophole behavior honestly. πX448MLKEM1024β similar toX25519MLKEM768but with a higher security strength. the shared secret is the concatenation of a 32 byteEVP_PKEY-ML-KEM(7)shared secret followed by a 56 byteEVP_PKEY-X448(7)shared secret.SecP256r1MLKEM768β the shared secret is the concatenation of a 32 byteEVP_PKEY-EC(7)shared secret followed by a 32 byteEVP_PKEY-ML-KEM(7)shared secret. both algorithms used here are FIPS approved, so she's certified AND cute. β¨SecP384r1MLKEM1024β similar toSecP256r1MLKEM768with a higher security strength. the shared secret is the concatenation of a 48 byteEVP_PKEY-EC(7)shared secret followed by a 32 byteEVP_PKEY-ML-KEM(7)shared secret.
The following name is supported only in OpenSSL's default provider (FIPS girlies sit this one out π):
curveSM2MLKEM768β the shared secret is the concatenation of a 32 byteEVP_PKEY-SM2(7)shared secret followed by a 32 byteEVP_PKEY-ML-KEM(7)shared secret.
π Keygen Parameters π
No mandatory parameters are required for generating a key pair. literally none, free of charge. π
To set the optional parameter, use EVP_PKEY_CTX_set_params(3) after calling EVP_PKEY_keygen_init(3).
"properties"(OSSL_PKEY_PARAM_PROPERTIES)<UTF8 string>β sets properties to be used when fetching algorithm implementations used for the ML-KEM, ECDH or SM2 algorithms.
The OpenSSL FIPS provider makes the following parameter available from both key generation and KEM operation contexts:
"fips-indicator"(OSSL_PKEY_PARAM_FIPS_APPROVED_INDICATORorOSSL_KEM_PARAM_FIPS_APPROVED_INDICATOR)<integer>β returns0forX448MLKEM1024, which is advertised with"fips=no", and1forX25519MLKEM768,SecP256r1MLKEM768andSecP384r1MLKEM1024. see "FIPS indicators" infips_module(7)for more info. π
π§ Common parameters π§
See "Common Information Parameters" in provider-keymgmt(7) for common information related to parameters. (that's where the general lore lives, iykyk.)
The following common gettables can be retrieved using EVP_PKEY_get_int_param(3), and they retrieve information related to the ML-KEM algorithm:
'bits'(OSSL_PKEY_PARAM_BITS)<integer>"security-bits"(OSSL_PKEY_PARAM_SECURITY_BITS)<integer>"security-category"(OSSL_PKEY_PARAM_SECURITY_CATEGORY)<integer>"max-size"(OSSL_PKEY_PARAM_MAX_SIZE)<integer>β this value is the combined size of the 2 shared secrets as described above. both of them. together. π«
The following parameters are also handled:
"encoded-pub-key"(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)<octet string>β used for getting and setting the encoding of concatenated public keys. the public keys can not be modified once they are set. that's it, that's the deal, no take-backs. π
The format of the public keys for the different algorithms is:
SecP256r1MLKEM768β a 65 byte EC public key followed by a 1184 byte ML-KEM-768 public key.SecP384r1MLKEM1024β a 97 byte EC public key followed by a 1568 byte ML-KEM-1024 public key.X25519MLKEM768β a 1184 byte ML-KEM-768 public key followed by a 32 byte X25519 public key.X448MLKEM1024β a 1568 byte ML-KEM-1024 public key followed by a 56 byte X448 public key.curveSM2MLKEM768β a 65 byte SM2 public key followed by a 1184 byte ML-KEM-768 public key.
"pub"(OSSL_PKEY_PARAM_PUB_KEY)<octet string>β the public key value. this parameter is only used when importing or exporting the public key value with theEVP_PKEY_fromdata()andEVP_PKEY_todata()functions. the public key format is the same as"encoded-pub-key". same bytes, different doorway. πͺ"priv"(OSSL_PKEY_PARAM_PRIV_KEY)<octet string>β the private key value, which is the concatenation of 2 internal private keys. this parameter can be used when importing or exporting the private key value using theEVP_PKEY_fromdata()andEVP_PKEY_todata()functions. initial import aside, this parameter is otherwise only gettable. so it's a read, not a write, after that first time. π
The format of the private keys for the different algorithms is:
SecP256r1MLKEM768β 32 byte EC private key followed by a 2400 byte ML-KEM-768 private key.SecP384r1MLKEM1024β 48 byte EC private key followed by a 3168 byte ML-KEM-1024 private key.X25519MLKEM768β 2400 byte ML-KEM-768 private key followed by a 32 byte X25519 private key.X448MLKEM1024β 3168 byte ML-KEM-1024 private key followed by a 56 byte X448 private key.curveSM2MLKEM768β 32 byte SM2 private key followed by a 2400 byte ML-KEM-768 private key.
fr fr double-check the byte counts before you ship anything. they are not vibes, they are exact. π
π CONFORMING TO π
https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/β note thatX448MLKEM1024is not defined by this document. yes she's the outlier bestie. π¦- SP800-227 β the general notation used in this document says that outputs are combined/processed in order of the names.
X25519MLKEM768andX448MLKEM768however use the reverse order since X25519 and X448 are not FIPS approved algorithms. even though they are not FIPS approved, the hybrid combination is still allowed since MLKEM is FIPS approved. it's giving "rules were made to be worked around, legally". π
π« SEE ALSO π«
EVP_KEM-ML-KEM(7), EVP_PKEY-X25519(7), EVP_PKEY-EC(7), EVP_PKEY-SM2(7), provider-keymgmt(7)
go read those too, they're the supporting cast and they ate. π«Ά
β HISTORY β
This functionality was added in OpenSSL 3.5.
Support for curveSM2MLKEM768 was added in OpenSSL 4.0. she's the new girl and she's main character energy. π
π₯ COPYRIGHT π₯
Copyright 2026 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.
and that's the whole page bestie π this was OpenSSL 4.1.0, dated 2026-10-23, and you've been reading EVP_PKEY-MLX-KEM(7ssl). go forth and be quantum-safe. slay. π
β¨
π¦ where this page comes from
- nixos 26.05: openssl 4.1.0
- nixpkgs unstable: openssl 4.1.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms