]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[tls] Add support for RSA-PSS signature scheme
authorMichael Brown <mcb30@ipxe.org>
Wed, 6 May 2026 21:06:16 +0000 (22:06 +0100)
committerMichael Brown <mcb30@ipxe.org>
Thu, 7 May 2026 13:29:15 +0000 (14:29 +0100)
The RSA-PSS signature scheme is crowbarred somewhat awkwardly into TLS
version 1.2.  Certificates with the standard rsaEncryption OID in the
public key may be used with either PKCS#1 or RSA-PSS, which breaks the
straightforward mapping between the OID and the signature algorithm.

Extend the definition of a TLS signature hash algorithm to include a
required OID-identified algorithm in the certificate's public key.
This allows us to define signature schemes such as rsa_pss_rsae_sha256
where the signature scheme uses an algorithm that differs from the
algorithm identified in the certificate's public key.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
13 files changed:
src/crypto/mishmash/ecdsa_sha224.c
src/crypto/mishmash/ecdsa_sha256.c
src/crypto/mishmash/ecdsa_sha384.c
src/crypto/mishmash/ecdsa_sha512.c
src/crypto/mishmash/oid_rsa_pss.c [new file with mode: 0644]
src/crypto/mishmash/rsa_sha1.c
src/crypto/mishmash/rsa_sha224.c
src/crypto/mishmash/rsa_sha256.c
src/crypto/mishmash/rsa_sha384.c
src/crypto/mishmash/rsa_sha512.c
src/include/ipxe/asn1.h
src/include/ipxe/tls.h
src/net/tls.c

index fcd9baf22b2e5e4b9d77c24effc31aae35406bab..d53363bac9ff5d2242cf97ea23222bf2fc41449f 100644 (file)
@@ -45,6 +45,7 @@ struct asn1_algorithm ecdsa_with_sha224_algorithm __asn1_algorithm = {
 struct tls_signature_hash_algorithm
 tls_ecdsa_sha224 __tls_sig_hash_algorithm = {
        .code = htons ( TLS_ECDSA_SHA224_ALGORITHM ),
+       .algorithm = &ecpubkey_algorithm,
        .pubkey = &ecdsa_algorithm,
        .digest = &sha224_algorithm,
 };
index 0135f4c570dae6117a47798ecff4ef2e4c6ab494..17bc87f0299d8f33de76102c456561f808e119b9 100644 (file)
@@ -45,6 +45,7 @@ struct asn1_algorithm ecdsa_with_sha256_algorithm __asn1_algorithm = {
 struct tls_signature_hash_algorithm
 tls_ecdsa_sha256 __tls_sig_hash_algorithm = {
        .code = htons ( TLS_ECDSA_SHA256_ALGORITHM ),
+       .algorithm = &ecpubkey_algorithm,
        .pubkey = &ecdsa_algorithm,
        .digest = &sha256_algorithm,
 };
index e6de2b8ef65e382e6d6bcf7d8a63ad32242c4230..bfaf25b157689369af707355ef6e1902e43d18ba 100644 (file)
@@ -45,6 +45,7 @@ struct asn1_algorithm ecdsa_with_sha384_algorithm __asn1_algorithm = {
 struct tls_signature_hash_algorithm
 tls_ecdsa_sha384 __tls_sig_hash_algorithm = {
        .code = htons ( TLS_ECDSA_SHA384_ALGORITHM ),
+       .algorithm = &ecpubkey_algorithm,
        .pubkey = &ecdsa_algorithm,
        .digest = &sha384_algorithm,
 };
index 2d97566b2cb2b63bd4ee57e5dcb4014fca0c5ccd..49931e5aeba13cd5057c80522cb78fca942a549e 100644 (file)
@@ -45,6 +45,7 @@ struct asn1_algorithm ecdsa_with_sha512_algorithm __asn1_algorithm = {
 struct tls_signature_hash_algorithm
 tls_ecdsa_sha512 __tls_sig_hash_algorithm = {
        .code = htons ( TLS_ECDSA_SHA512_ALGORITHM ),
+       .algorithm = &ecpubkey_algorithm,
        .pubkey = &ecdsa_algorithm,
        .digest = &sha512_algorithm,
 };
diff --git a/src/crypto/mishmash/oid_rsa_pss.c b/src/crypto/mishmash/oid_rsa_pss.c
new file mode 100644 (file)
index 0000000..a8eae79
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2026 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
+
+#include <ipxe/rsa.h>
+#include <ipxe/asn1.h>
+
+/** "rsassa-pss" object identifier */
+static uint8_t oid_rsassa_pss[] = { ASN1_OID_RSASSA_PSS };
+
+/** "rsassa-pss" OID-identified algorithm */
+struct asn1_algorithm rsassa_pss_algorithm __asn1_algorithm = {
+       .name = "rsassa-pss",
+       .pubkey = &rsa_pss_algorithm,
+       .digest = NULL,
+       .oid = ASN1_CURSOR ( oid_rsassa_pss ),
+};
index 21991c210b1d7fffd76b5d08f07f4a3dc1fb08e5..ef8b924bc4633940b20229d98220478fbd24e2e2 100644 (file)
@@ -56,6 +56,7 @@ struct rsa_digestinfo_prefix rsa_sha1_prefix __rsa_digestinfo_prefix = {
 /** RSA with SHA-1 signature hash algorithm */
 struct tls_signature_hash_algorithm tls_rsa_sha1 __tls_sig_hash_algorithm = {
        .code = htons ( TLS_RSA_SHA1_ALGORITHM ),
+       .algorithm = &rsa_encryption_algorithm,
        .pubkey = &rsa_algorithm,
        .digest = &sha1_algorithm,
 };
index ce8f6b65e69fa0f86bfc24fadddfe0b2e2df8e57..1b969e3b850b0a6f1644a6aa098dbe5ef8c8843e 100644 (file)
@@ -56,6 +56,7 @@ struct rsa_digestinfo_prefix rsa_sha224_prefix __rsa_digestinfo_prefix = {
 /** RSA with SHA-224 signature hash algorithm */
 struct tls_signature_hash_algorithm tls_rsa_sha224 __tls_sig_hash_algorithm = {
        .code = htons ( TLS_RSA_SHA224_ALGORITHM ),
+       .algorithm = &rsa_encryption_algorithm,
        .pubkey = &rsa_algorithm,
        .digest = &sha224_algorithm,
 };
index f672f0f0f3c100ed9bd98431e88324919d4efe57..084e60ca2d5fc65e0bd6bf45519b9a2213828298 100644 (file)
@@ -56,6 +56,25 @@ struct rsa_digestinfo_prefix rsa_sha256_prefix __rsa_digestinfo_prefix = {
 /** RSA with SHA-256 signature hash algorithm */
 struct tls_signature_hash_algorithm tls_rsa_sha256 __tls_sig_hash_algorithm = {
        .code = htons ( TLS_RSA_SHA256_ALGORITHM ),
+       .algorithm = &rsa_encryption_algorithm,
        .pubkey = &rsa_algorithm,
        .digest = &sha256_algorithm,
 };
+
+/** RSA-PSS with rsaEncryption OID and SHA-256 signature hash algorithm */
+struct tls_signature_hash_algorithm
+tls_rsa_pss_rsae_sha256 __tls_sig_hash_algorithm = {
+       .code = htons ( TLS_RSA_PSS_RSAE_SHA256_ALGORITHM ),
+       .algorithm = &rsa_encryption_algorithm,
+       .pubkey = &rsa_pss_algorithm,
+       .digest = &sha256_algorithm,
+};
+
+/** RSA-PSS with RSASSA-PSS OID and SHA-256 signature hash algorithm */
+struct tls_signature_hash_algorithm
+tls_rsa_pss_pss_sha256 __tls_sig_hash_algorithm = {
+       .code = htons ( TLS_RSA_PSS_PSS_SHA256_ALGORITHM ),
+       .algorithm = &rsassa_pss_algorithm,
+       .pubkey = &rsa_pss_algorithm,
+       .digest = &sha256_algorithm,
+};
index bb8e06efb9a064d841b7cb9d4c8a61418dcd7fe6..977b3269d58118285f6e2e44acfdc39aea81ec91 100644 (file)
@@ -56,6 +56,25 @@ struct rsa_digestinfo_prefix rsa_sha384_prefix __rsa_digestinfo_prefix = {
 /** RSA with SHA-384 signature hash algorithm */
 struct tls_signature_hash_algorithm tls_rsa_sha384 __tls_sig_hash_algorithm = {
        .code = htons ( TLS_RSA_SHA384_ALGORITHM ),
+       .algorithm = &rsa_encryption_algorithm,
        .pubkey = &rsa_algorithm,
        .digest = &sha384_algorithm,
 };
+
+/** RSA-PSS with rsaEncryption OID and SHA-384 signature hash algorithm */
+struct tls_signature_hash_algorithm
+tls_rsa_pss_rsae_sha384 __tls_sig_hash_algorithm = {
+       .code = htons ( TLS_RSA_PSS_RSAE_SHA384_ALGORITHM ),
+       .algorithm = &rsa_encryption_algorithm,
+       .pubkey = &rsa_pss_algorithm,
+       .digest = &sha384_algorithm,
+};
+
+/** RSA-PSS with RSASSA-PSS OID and SHA-384 signature hash algorithm */
+struct tls_signature_hash_algorithm
+tls_rsa_pss_pss_sha384 __tls_sig_hash_algorithm = {
+       .code = htons ( TLS_RSA_PSS_PSS_SHA384_ALGORITHM ),
+       .algorithm = &rsassa_pss_algorithm,
+       .pubkey = &rsa_pss_algorithm,
+       .digest = &sha384_algorithm,
+};
index 48d1fe2ddc0966d2a0cbf01c96b2c23b7f8b3ed2..e62daa6ffc2cc4849255a1a450f96ec626e00efb 100644 (file)
@@ -56,6 +56,25 @@ struct rsa_digestinfo_prefix rsa_sha512_prefix __rsa_digestinfo_prefix = {
 /** RSA with SHA-512 signature hash algorithm */
 struct tls_signature_hash_algorithm tls_rsa_sha512 __tls_sig_hash_algorithm = {
        .code = htons ( TLS_RSA_SHA512_ALGORITHM ),
+       .algorithm = &rsa_encryption_algorithm,
        .pubkey = &rsa_algorithm,
        .digest = &sha512_algorithm,
 };
+
+/** RSA-PSS with rsaEncryption OID and SHA-512 signature hash algorithm */
+struct tls_signature_hash_algorithm
+tls_rsa_pss_rsae_sha512 __tls_sig_hash_algorithm = {
+       .code = htons ( TLS_RSA_PSS_RSAE_SHA512_ALGORITHM ),
+       .algorithm = &rsa_encryption_algorithm,
+       .pubkey = &rsa_pss_algorithm,
+       .digest = &sha512_algorithm,
+};
+
+/** RSA-PSS with RSASSA-PSS OID and SHA-512 signature hash algorithm */
+struct tls_signature_hash_algorithm
+tls_rsa_pss_pss_sha512 __tls_sig_hash_algorithm = {
+       .code = htons ( TLS_RSA_PSS_PSS_SHA512_ALGORITHM ),
+       .algorithm = &rsassa_pss_algorithm,
+       .pubkey = &rsa_pss_algorithm,
+       .digest = &sha512_algorithm,
+};
index c5dcccb99712b46123018b6d4430063fce40906b..649b059d7b09e0aeefe29dc55d9ba49f4d61a113 100644 (file)
@@ -182,6 +182,12 @@ struct asn1_builder_header {
        ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ),      \
        ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 5 )
 
+/** ASN.1 OID for rsassa-pss (1.2.840.113549.1.1.10) */
+#define ASN1_OID_RSASSA_PSS                                    \
+       ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ),     \
+       ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ),      \
+       ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 10 )
+
 /** ASN.1 OID for sha256WithRSAEncryption (1.2.840.113549.1.1.11) */
 #define ASN1_OID_SHA256WITHRSAENCRYPTION                       \
        ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ),     \
@@ -437,6 +443,7 @@ struct asn1_algorithm {
 
 /* ASN.1 OID-identified algorithms */
 extern struct asn1_algorithm rsa_encryption_algorithm __asn1_algorithm;
+extern struct asn1_algorithm rsassa_pss_algorithm __asn1_algorithm;
 extern struct asn1_algorithm md5_with_rsa_encryption_algorithm __asn1_algorithm;
 extern struct asn1_algorithm
 sha1_with_rsa_encryption_algorithm __asn1_algorithm;
index 080c839d309a12bb9f20b3a64b49ad97badaa6e0..5d97287971a18825a04a54e66c039699eeecebcc 100644 (file)
@@ -123,6 +123,12 @@ struct tls_header {
 #define TLS_ECDSA_SHA384_ALGORITHM 0x0503
 #define TLS_RSA_SHA512_ALGORITHM 0x0601
 #define TLS_ECDSA_SHA512_ALGORITHM 0x0603
+#define TLS_RSA_PSS_RSAE_SHA256_ALGORITHM 0x0804
+#define TLS_RSA_PSS_RSAE_SHA384_ALGORITHM 0x0805
+#define TLS_RSA_PSS_RSAE_SHA512_ALGORITHM 0x0806
+#define TLS_RSA_PSS_PSS_SHA256_ALGORITHM 0x0809
+#define TLS_RSA_PSS_PSS_SHA384_ALGORITHM 0x080a
+#define TLS_RSA_PSS_PSS_SHA512_ALGORITHM 0x080b
 
 /* TLS server name extension */
 #define TLS_SERVER_NAME 0
@@ -284,6 +290,8 @@ struct tls_signature_hash_algorithm {
        struct digest_algorithm *digest;
        /** Public-key algorithm */
        struct pubkey_algorithm *pubkey;
+       /** Required certificate OID-identified algorithm */
+       struct asn1_algorithm *algorithm;
        /** Numeric code (in network-endian order) */
        uint16_t code;
 };
@@ -392,6 +400,8 @@ struct tls_server {
        struct x509_root *root;
        /** Certificate chain */
        struct x509_chain *chain;
+       /** Public key algorithm (within server certificate) */
+       struct asn1_algorithm *algorithm;
        /** Public key (within server certificate) */
        struct asn1_cursor key;
        /** Certificate validator */
index 93c82f8317764d8546554a9b9513d8d5985ce1c4..74ae70e0224f88166140e221fe57b1873a6f3b59 100644 (file)
@@ -1463,10 +1463,9 @@ static int tls_verify_dh_params ( struct tls_connection *tls,
                digest = sig_hash->digest;
                DBGC ( tls, "TLS %p using signature hash %s-%s\n",
                       tls, pubkey->name, digest->name );
-               if ( pubkey != cipherspec->suite->pubkey ) {
-                       DBGC ( tls, "TLS %p ServerKeyExchange incorrect "
-                              "signature algorithm %s (expected %s)\n", tls,
-                              pubkey->name, cipherspec->suite->pubkey->name );
+               if ( sig_hash->algorithm != tls->server.algorithm ) {
+                       DBGC ( tls, "TLS %p cannot use %s public key\n",
+                              tls, tls->server.algorithm->name );
                        return -EPERM_KEY_EXCHANGE;
                }
        } else {
@@ -2331,6 +2330,7 @@ static int tls_parse_chain ( struct tls_connection *tls,
        memset ( &tls->server.key, 0, sizeof ( tls->server.key ) );
        x509_chain_put ( tls->server.chain );
        tls->server.chain = NULL;
+       tls->server.algorithm = NULL;
 
        /* Create certificate chain */
        tls->server.chain = x509_alloc_chain();
@@ -2391,6 +2391,7 @@ static int tls_parse_chain ( struct tls_connection *tls,
        memset ( &tls->server.key, 0, sizeof ( tls->server.key ) );
        x509_chain_put ( tls->server.chain );
        tls->server.chain = NULL;
+       tls->server.algorithm = NULL;
  err_alloc_chain:
        return rc;
 }
@@ -3685,6 +3686,7 @@ static void tls_validator_done ( struct tls_connection *tls, int rc ) {
        }
 
        /* Extract the now trusted server public key */
+       tls->server.algorithm = cert->subject.public_key.algorithm;
        memcpy ( &tls->server.key, &cert->subject.public_key.raw,
                 sizeof ( tls->server.key ) );