Add support for RSASSA-PSS signatures (RFC8017) for use with module signing
and other public key cryptography done by the kernel.

Note that only signature verification is supported by the kernel.

Note further that this alters some of the same code as the MLDSA support,
so that needs to be applied first to avoid conflicts.

Signed-off-by: David Howells <[email protected]>
Reviewed-by: Ignat Korchagin <[email protected]>
cc: Lukas Wunner <[email protected]>
cc: Herbert Xu <[email protected]>
cc: [email protected]
cc: [email protected]
---
 Documentation/admin-guide/module-signing.rst |  5 ++-
 certs/Kconfig                                |  6 +++
 certs/Makefile                               |  1 +
 scripts/sign-file.c                          | 39 +++++++++++++++++++-
 4 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/Documentation/admin-guide/module-signing.rst 
b/Documentation/admin-guide/module-signing.rst
index 7f2f127dc76f..aa24715cd2d8 100644
--- a/Documentation/admin-guide/module-signing.rst
+++ b/Documentation/admin-guide/module-signing.rst
@@ -32,8 +32,9 @@ 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.
+algorithm is selected by data in the signature); RSASSA-PSS is allowed to use
+SHA512 only; ML-DSA does its own hashing, but is allowed to be used with a
+SHA512 hash for signed attributes.
 
 
 ==========================
diff --git a/certs/Kconfig b/certs/Kconfig
index 67a5786423b5..524d1747c541 100644
--- a/certs/Kconfig
+++ b/certs/Kconfig
@@ -27,6 +27,12 @@ config MODULE_SIG_KEY_TYPE_RSA
        help
         Use an RSA key for module signing.
 
+config MODULE_SIG_KEY_TYPE_RSASSA_PSS
+       bool "RSASSA-PSS"
+       select CRYPTO_RSA
+       help
+        Use an RSASSA-PSS key for module signing.
+
 config MODULE_SIG_KEY_TYPE_ECDSA
        bool "ECDSA"
        select CRYPTO_ECDSA
diff --git a/certs/Makefile b/certs/Makefile
index 3ee1960f9f4a..3b5a3a303f4c 100644
--- a/certs/Makefile
+++ b/certs/Makefile
@@ -42,6 +42,7 @@ targets += x509_certificate_list
 # boolean option and we unfortunately can't make it depend on !RANDCONFIG.
 ifeq ($(CONFIG_MODULE_SIG_KEY),certs/signing_key.pem)
 
+keytype-$(CONFIG_MODULE_SIG_KEY_TYPE_RSASSA_PSS) := -newkey rsassa-pss
 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
diff --git a/scripts/sign-file.c b/scripts/sign-file.c
index 547b97097230..800e2e2e36c3 100644
--- a/scripts/sign-file.c
+++ b/scripts/sign-file.c
@@ -233,6 +233,7 @@ int main(int argc, char **argv)
        EVP_PKEY *private_key;
 #ifndef USE_PKCS7
        CMS_ContentInfo *cms = NULL;
+       CMS_SignerInfo *signer;
        unsigned int use_keyid = 0;
 #else
        PKCS7 *pkcs7 = NULL;
@@ -338,12 +339,46 @@ int main(int argc, char **argv)
 
                flags |= use_signed_attrs;
 
+               if (EVP_PKEY_is_a(private_key, "RSASSA-PSS")) {
+                       EVP_PKEY_CTX *pkctx;
+                       char mdname[1024] = {};
+
+                       pkctx = EVP_PKEY_CTX_new(private_key, NULL);
+
+                       ERR(!EVP_PKEY_sign_init(pkctx), "EVP_PKEY_sign_init");
+                       ERR(!EVP_PKEY_CTX_set_rsa_padding(pkctx, 
RSA_PKCS1_PSS_PADDING),
+                           "EVP_PKEY_CTX_set_rsa_padding");
+                       ERR(!EVP_PKEY_CTX_set_rsa_mgf1_md_name(pkctx, 
hash_algo, NULL),
+                           "EVP_PKEY_CTX_set_rsa_mgf1_md_name");
+
+                       ERR(!EVP_PKEY_CTX_get_rsa_mgf1_md_name(pkctx, mdname, 
sizeof(mdname)),
+                           "EVP_PKEY_CTX_get_rsa_mgf1_md_name");
+                       printf("RSASSA-PSS %s\n", mdname);
+                       flags |= CMS_KEY_PARAM;
+               }
+
                /* Load the signature message from the digest buffer. */
                cms = CMS_sign(NULL, NULL, NULL, NULL, flags);
                ERR(!cms, "CMS_sign");
 
-               ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo, 
flags),
-                   "CMS_add1_signer");
+               signer = CMS_add1_signer(cms, x509, private_key, digest_algo, 
flags);
+               ERR(!signer, "CMS_add1_signer");
+
+               if (EVP_PKEY_is_a(private_key, "RSASSA-PSS")) {
+                       EVP_PKEY_CTX *pkctx;
+                       char mdname[1024] = {};
+
+                       pkctx = CMS_SignerInfo_get0_pkey_ctx(signer);
+                       ERR(!EVP_PKEY_CTX_set_rsa_padding(pkctx, 
RSA_PKCS1_PSS_PADDING),
+                           "EVP_PKEY_CTX_set_rsa_padding");
+                       ERR(!EVP_PKEY_CTX_set_rsa_mgf1_md_name(pkctx, 
hash_algo, NULL),
+                           "EVP_PKEY_CTX_set_rsa_mgf1_md_name");
+
+                       ERR(!EVP_PKEY_CTX_get_rsa_mgf1_md_name(pkctx, mdname, 
sizeof(mdname)),
+                           "EVP_PKEY_CTX_get_rsa_mgf1_md_name");
+                       printf("RSASSA-PSS %s\n", mdname);
+               }
+
                ERR(CMS_final(cms, bm, NULL, flags) != 1,
                    "CMS_final");
 


Reply via email to