On Wed, Jan 21, 2026 at 10:36:07PM +0000, David Howells wrote: > Allow ML-DSA module signing to be enabled. > > Note that OpenSSL's CMS_*() function suite does not, as of OpenSSL-3.6, > support the use of CMS_NOATTR with ML-DSA, so the prohibition against using > signedAttrs with module signing has to be removed. The selected digest > then applies only to the algorithm used to calculate the digest stored in > the messageDigest attribute. The OpenSSL development branch has patches > applied that fix this[1], but it appears that that will only be available > in OpenSSL-4. > > [1] https://github.com/openssl/openssl/pull/28923 > > sign-file won't set CMS_NOATTR if openssl is earlier than v4, resulting in > the use of signed attributes. > > The ML-DSA algorithm takes the raw data to be signed without regard to what > digest algorithm is specified in the CMS message. The CMS specified digest > algorithm is ignored unless signedAttrs are used; in such a case, only > SHA512 is permitted. > > Signed-off-by: David Howells <[email protected]> > cc: Eric Biggers <[email protected]> > cc: Lukas Wunner <[email protected]> > cc: Ignat Korchagin <[email protected]> > cc: Stephan Mueller <[email protected]> > cc: Herbert Xu <[email protected]> > cc: [email protected] > cc: [email protected] > --- > Documentation/admin-guide/module-signing.rst | 16 +++++---- > certs/Kconfig | 30 +++++++++++++++++ > certs/Makefile | 3 ++ > crypto/asymmetric_keys/pkcs7_verify.c | 4 --- > scripts/sign-file.c | 34 +++++++++++++++----- > 5 files changed, 68 insertions(+), 19 deletions(-) > > diff --git a/Documentation/admin-guide/module-signing.rst > b/Documentation/admin-guide/module-signing.rst > index a8667a777490..7f2f127dc76f 100644 > --- a/Documentation/admin-guide/module-signing.rst > +++ b/Documentation/admin-guide/module-signing.rst > @@ -28,10 +28,12 @@ trusted userspace bits. > > This facility uses X.509 ITU-T standard certificates to encode the public > keys > involved. The signatures are not themselves encoded in any industrial > standard > -type. The built-in facility currently only supports the RSA & NIST P-384 > ECDSA > -public key signing standard (though it is pluggable and permits others to be > -used). The possible hash algorithms that can be used are SHA-2 and SHA-3 of > -sizes 256, 384, and 512 (the algorithm is selected by data in the signature). > +type. The built-in facility currently only supports the RSA, NIST P-384 > ECDSA > +and NIST FIPS-204 ML-DSA public key signing standards (though it is pluggable > +and permits others to be used). For RSA and ECDSA, the possible hash > +algorithms that can be used are SHA-2 and SHA-3 of sizes 256, 384, and 512 > (the > +algorithm is selected by data in the signature); ML-DSA does its own hashing, > +but is allowed to be used with a SHA512 hash for signed attributes. > > > ========================== > @@ -146,9 +148,9 @@ into vmlinux) using parameters in the:: > > file (which is also generated if it does not already exist). > > -One can select between RSA (``MODULE_SIG_KEY_TYPE_RSA``) and ECDSA > -(``MODULE_SIG_KEY_TYPE_ECDSA``) to generate either RSA 4k or NIST > -P-384 keypair. > +One can select between RSA (``MODULE_SIG_KEY_TYPE_RSA``), ECDSA > +(``MODULE_SIG_KEY_TYPE_ECDSA``) and ML-DSA (``MODULE_SIG_KEY_TYPE_MLDSA_*``) > to > +generate an RSA 4k, a NIST P-384 keypair or an ML-DSA 44, 65 or 87 keypair. > > It is strongly recommended that you provide your own x509.genkey file. > > diff --git a/certs/Kconfig b/certs/Kconfig > index 78307dc25559..2b088ef58373 100644 > --- a/certs/Kconfig > +++ b/certs/Kconfig > @@ -39,6 +39,36 @@ config MODULE_SIG_KEY_TYPE_ECDSA > Note: Remove all ECDSA signing keys, e.g. certs/signing_key.pem, > when falling back to building Linux 5.14 and older kernels. > > +config MODULE_SIG_KEY_TYPE_MLDSA_44 > + bool "ML-DSA-44" > + select CRYPTO_MLDSA > + help > + Use an ML-DSA-44 key (NIST FIPS 204) for module signing. ML-DSA > + support requires OpenSSL-3.5 minimum; preferably OpenSSL-4+. With > + the latter, the entire module body will be signed; with the former, > + signedAttrs will be used as it lacks support for CMS_NOATTR with > + ML-DSA. > + > +config MODULE_SIG_KEY_TYPE_MLDSA_65 > + bool "ML-DSA-65" > + select CRYPTO_MLDSA > + help > + Use an ML-DSA-65 key (NIST FIPS 204) for module signing. ML-DSA > + support requires OpenSSL-3.5 minimum; preferably OpenSSL-4+. With > + the latter, the entire module body will be signed; with the former, > + signedAttrs will be used as it lacks support for CMS_NOATTR with > + ML-DSA. > + > +config MODULE_SIG_KEY_TYPE_MLDSA_87 > + bool "ML-DSA-87" > + select CRYPTO_MLDSA > + help > + Use an ML-DSA-87 key (NIST FIPS 204) for module signing. ML-DSA > + support requires OpenSSL-3.5 minimum; preferably OpenSSL-4+. With > + the latter, the entire module body will be signed; with the former, > + signedAttrs will be used as it lacks support for CMS_NOATTR with > + ML-DSA. > + > endchoice > > config SYSTEM_TRUSTED_KEYRING > diff --git a/certs/Makefile b/certs/Makefile > index f6fa4d8d75e0..3ee1960f9f4a 100644 > --- a/certs/Makefile > +++ b/certs/Makefile > @@ -43,6 +43,9 @@ targets += x509_certificate_list > ifeq ($(CONFIG_MODULE_SIG_KEY),certs/signing_key.pem) > > keytype-$(CONFIG_MODULE_SIG_KEY_TYPE_ECDSA) := -newkey ec -pkeyopt > ec_paramgen_curve:secp384r1 > +keytype-$(CONFIG_MODULE_SIG_KEY_TYPE_MLDSA_44) := -newkey ml-dsa-44 > +keytype-$(CONFIG_MODULE_SIG_KEY_TYPE_MLDSA_65) := -newkey ml-dsa-65 > +keytype-$(CONFIG_MODULE_SIG_KEY_TYPE_MLDSA_87) := -newkey ml-dsa-87 > > quiet_cmd_gen_key = GENKEY $@ > cmd_gen_key = openssl req -new -nodes -utf8 -$(CONFIG_MODULE_SIG_HASH) > -days 36500 \ > diff --git a/crypto/asymmetric_keys/pkcs7_verify.c > b/crypto/asymmetric_keys/pkcs7_verify.c > index a5b2ed4d53fd..75d1d694dc7b 100644 > --- a/crypto/asymmetric_keys/pkcs7_verify.c > +++ b/crypto/asymmetric_keys/pkcs7_verify.c > @@ -431,10 +431,6 @@ int pkcs7_verify(struct pkcs7_message *pkcs7, > pr_warn("Invalid module sig (not pkcs7-data)\n"); > return -EKEYREJECTED; > } > - if (pkcs7->have_authattrs) { > - pr_warn("Invalid module sig (has authattrs)\n"); > - return -EKEYREJECTED; > - } > break; > case VERIFYING_FIRMWARE_SIGNATURE: > if (pkcs7->data_type != OID_data) { > diff --git a/scripts/sign-file.c b/scripts/sign-file.c > index 7070245edfc1..547b97097230 100644 > --- a/scripts/sign-file.c > +++ b/scripts/sign-file.c > @@ -315,18 +315,36 @@ int main(int argc, char **argv) > ERR(!digest_algo, "EVP_get_digestbyname"); > > #ifndef USE_PKCS7 > + > + unsigned int flags = > + CMS_NOCERTS | > + CMS_PARTIAL | > + CMS_BINARY | > + CMS_DETACHED | > + CMS_STREAM | > + CMS_NOSMIMECAP | > + CMS_NO_SIGNING_TIME | > + use_keyid; > + > + if ((EVP_PKEY_is_a(private_key, "ML-DSA-44") || > + EVP_PKEY_is_a(private_key, "ML-DSA-65") || > + EVP_PKEY_is_a(private_key, "ML-DSA-87")) && > + OPENSSL_VERSION_MAJOR < 4) { > + /* ML-DSA + CMS_NOATTR is not supported in openssl-3.5 > + * and before. > + */ > + use_signed_attrs = 0; > + } > + > + flags |= use_signed_attrs; > + > /* Load the signature message from the digest buffer. */ > - cms = CMS_sign(NULL, NULL, NULL, NULL, > - CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | > - CMS_DETACHED | CMS_STREAM); > + cms = CMS_sign(NULL, NULL, NULL, NULL, flags); > ERR(!cms, "CMS_sign"); > > - ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo, > - CMS_NOCERTS | CMS_BINARY | > - CMS_NOSMIMECAP | use_keyid | > - use_signed_attrs), > + ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo, > flags), > "CMS_add1_signer"); > - ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) != 1, > + ERR(CMS_final(cms, bm, NULL, flags) != 1, > "CMS_final"); > > #else >
LGTM Reviewed-by: Jarkko Sakkinen <[email protected]> BR, Jarkko
