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..8e39a80c7abe 100644 --- a/certs/Kconfig +++ b/certs/Kconfig @@ -39,6 +39,39 @@ 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 + depends on OPENSSL_SUPPORTS_ML_DSA + 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 + depends on OPENSSL_SUPPORTS_ML_DSA + 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 + depends on OPENSSL_SUPPORTS_ML_DSA + 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 @@ -154,4 +187,11 @@ config SYSTEM_BLACKLIST_AUTH_UPDATE keyring. The PKCS#7 signature of the description is set in the key payload. Blacklist keys cannot be removed. +config OPENSSL_SUPPORTS_ML_DSA + def_bool $(success, openssl list -key-managers | grep -q ML-DSA-87) + help + Support for ML-DSA-44/65/87 was added in openssl-3.5, so as long + as older versions are supported, the key types may only be + set after testing the installed binary for support. + endmenu 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/scripts/sign-file.c b/scripts/sign-file.c index 7070245edfc1..78276b15ab23 100644 --- a/scripts/sign-file.c +++ b/scripts/sign-file.c @@ -27,7 +27,7 @@ #include #include #include -#if OPENSSL_VERSION_MAJOR >= 3 +#if OPENSSL_VERSION_NUMBER >= 0x30000000L # define USE_PKCS11_PROVIDER # include # include @@ -315,18 +315,39 @@ 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 | +#ifdef CMS_NO_SIGNING_TIME + CMS_NO_SIGNING_TIME | +#endif + use_keyid; + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_VERSION_NUMBER < 0x40000000L + 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")) { + /* ML-DSA + CMS_NOATTR is not supported in openssl-3.5 + * and before. + */ + use_signed_attrs = 0; + } +#endif + + 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