certtool: generate RSA-PSS certificates from RSA keys
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Mon, 15 Apr 2019 12:32:55 +0000 (14:32 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 20 Apr 2019 15:12:44 +0000 (17:12 +0200)
When generating certificates it was not possible to generate
an RSA-PSS certificate from an RSA key (common scenario). This
fixes the certificate generation to include such a method.

Ironically there was a test for this scenario but the test
was limited to checking that the combination of certtool parameters
succeeded; modified the test to check the textual expression of
the certificate for the RSA-PSS indicators.

Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
src/certtool-args.def
src/certtool.c
tests/cert-tests/certtool-rsa-pss
tests/cert-tests/rsa-pss-pad

index 27ca2c8ed49fabed2986c1bd0e16ac324664f286..35741a21c8787acf865fbb67be7987ef5b0a672d 100644 (file)
@@ -200,7 +200,9 @@ flag = {
     arg-type  = string;
     descrip   = "Specify the key type to use on key generation";
     doc = "This option can be combined with --generate-privkey, to specify
-the key type to be generated. Valid options are, 'rsa', 'rsa-pss', 'dsa', 'ecdsa', and 'ed25519'.";
+the key type to be generated. Valid options are, 'rsa', 'rsa-pss', 'dsa', 'ecdsa', and 'ed25519'.
+When combined with certificate generation it can be used to specify an
+RSA-PSS certificate when an RSA key is given.";
 };
 
 flag = {
index 11dc27a6fd6d994ed918cd172340f89b1c4154d2..4d2b7c6a9800649c07181d8b162dca9306b51754 100644 (file)
@@ -128,6 +128,21 @@ int main(int argc, char **argv)
        return 0;
 }
 
+#define SET_SPKI_PARAMS(spki, cinfo) \
+       do { \
+               unsigned _salt_size; \
+               if (!cinfo->hash) { \
+                       fprintf(stderr, "You must provide the hash algorithm and optionally the salt size for RSA-PSS\n"); \
+                       app_exit(1); \
+               } \
+               if (HAVE_OPT(SALT_SIZE)) { \
+                       _salt_size = OPT_VALUE_SALT_SIZE; \
+               } else { \
+                       _salt_size = gnutls_hash_get_len(cinfo->hash); \
+               } \
+               gnutls_x509_spki_set_rsa_pss_params(spki, cinfo->hash, _salt_size); \
+       } while(0)
+
 static gnutls_x509_privkey_t
 generate_private_key_int(common_info_st * cinfo)
 {
@@ -220,20 +235,8 @@ generate_private_key_int(common_info_st * cinfo)
        }
 
        if (key_type == GNUTLS_PK_RSA_PSS && (cinfo->hash || HAVE_OPT(SALT_SIZE))) {
-               unsigned salt_size;
-
-               if (!cinfo->hash) {
-                       fprintf(stderr, "You must provide the hash algorithm and optionally the salt size for RSA-PSS\n");
-                       app_exit(1);
-               }
-
-               if (HAVE_OPT(SALT_SIZE)) {
-                       salt_size = OPT_VALUE_SALT_SIZE;
-               } else {
-                       salt_size = gnutls_hash_get_len(cinfo->hash);
-               }
 
-               gnutls_x509_spki_set_rsa_pss_params(spki, cinfo->hash, salt_size);
+               SET_SPKI_PARAMS(spki, cinfo);
 
                kdata[kdata_size].type = GNUTLS_KEYGEN_SPKI;
                kdata[kdata_size].data = (void*)spki;
@@ -308,6 +311,7 @@ generate_certificate(gnutls_privkey_t * ret_key,
                     common_info_st * cinfo)
 {
        gnutls_x509_crt_t crt;
+       gnutls_x509_spki_t spki;
        gnutls_privkey_t key = NULL;
        gnutls_pubkey_t pubkey;
        size_t size;
@@ -715,11 +719,10 @@ generate_certificate(gnutls_privkey_t * ret_key,
                app_exit(1);
        }
 
+
        /* Set algorithm parameter restriction in CAs.
         */
        if (pk == GNUTLS_PK_RSA_PSS && ca_status && key) {
-               gnutls_x509_spki_t spki;
-
                result = gnutls_x509_spki_init(&spki);
                if (result < 0) {
                        fprintf(stderr, "spki_init: %s\n",
@@ -737,6 +740,25 @@ generate_certificate(gnutls_privkey_t * ret_key,
                        }
                }
 
+               gnutls_x509_spki_deinit(spki);
+
+       } else if (pk == GNUTLS_PK_RSA && req_key_type == GNUTLS_PK_RSA_PSS) {
+               result = gnutls_x509_spki_init(&spki);
+               if (result < 0) {
+                       fprintf(stderr, "spki_init: %s\n",
+                               gnutls_strerror(result));
+                       app_exit(1);
+               }
+
+               SET_SPKI_PARAMS(spki, cinfo);
+
+               result = gnutls_x509_crt_set_spki(crt, spki, 0);
+               if (result < 0) {
+                       fprintf(stderr, "error setting RSA-PSS SPKI information: %s\n",
+                               gnutls_strerror(result));
+                       app_exit(1);
+               }
+
                gnutls_x509_spki_deinit(spki);
        }
 
index f8126a552319ff7bc140d45fbb9e380c629611a5..baa819c6aca099e2986d81199526304ddf5b1661 100755 (executable)
@@ -49,7 +49,7 @@ if test "${rc}" != "0"; then
        exit 1
 fi
 
-${VALGRIND} "${CERTTOOL}" -k --password '' --infile "$OUTFILE"
+${VALGRIND} "${CERTTOOL}" -k --password '' --infile "$OUTFILE" >/dev/null
 rc=$?
 if test "${rc}" != "0"; then
        echo "Could not read generated an RSA-PSS key ($i)"
@@ -68,6 +68,8 @@ if test "${rc}" != "0"; then
        exit 1
 fi
 
+rm -f "${TMPFILE}"
+
 # Create an RSA-PSS certificate from an RSA-PSS private key, with
 # mismatched parameters
 for j in sha256 sha384 sha512;do
@@ -82,6 +84,7 @@ if test "$j" != "$j" && "${rc}" = "0"; then
        exit 1
 fi
 done
+rm -f "${TMPFILE}"
 
 # Create an RSA-PSS certificate from an RSA key
 ${VALGRIND} "${CERTTOOL}" --generate-certificate --key-type rsa-pss \
@@ -97,6 +100,15 @@ if test "${rc}" != "0"; then
        exit 1
 fi
 
+${CERTTOOL} -i --infile ${TMPFILE}|grep -i "Subject Public Key Algorithm: RSA-PSS"
+if test $? != 0;then
+       echo "Generated certificate is not RSA-PSS"
+       cat ${TMPFILE}
+       exit 1
+fi
+
+rm -f "${TMPFILE}"
+
 # Create an RSA certificate from an RSA key, and sign it with RSA-PSS
 ${VALGRIND} "${CERTTOOL}" --generate-certificate --rsa --sign-params rsa-pss \
            --load-privkey "${srcdir}/../../doc/credentials/x509/key-rsa.pem" \
@@ -110,6 +122,23 @@ if test "${rc}" != "0"; then
        echo "Could not generate an RSA-PSS certificate"
        exit 1
 fi
+
+${CERTTOOL} -i --infile ${TMPFILE}|tr -d '\r'|grep -i 'Subject Public Key Algorithm: RSA$' >/dev/null
+if test $? != 0;then
+       echo "Generated certificate is not RSA"
+       cat ${TMPFILE}
+       exit 1
+fi
+
+${CERTTOOL} -i --infile ${TMPFILE}|grep -i "Signature Algorithm: RSA-PSS"
+if test $? != 0;then
+       echo "Generated certificate is not signed with RSA-PSS"
+       cat ${TMPFILE}
+       exit 1
+fi
+
+rm -f "${TMPFILE}"
+
 done
 
 # Convert an RSA-PSS key to an RSA key
@@ -133,6 +162,8 @@ fi
 
 echo "RSA-PSS to RSA conversion was successful"
 
+rm -f "${TMPFILE}"
+
 export TZ="UTC"
 
 . ${srcdir}/../scripts/common.sh
index e2eccfbe8ee77e1c467279ad139437ee4f814e44..d9a05e4e0f9fdb0639bc0a8c4d2a57645be9957d 100755 (executable)
@@ -44,9 +44,9 @@ check_for_datefudge
 for i in sha256 sha384 sha512;do
 datefudge -s "2007-04-22" \
 "${CERTTOOL}" --generate-self-signed --key-type rsa-pss \
-               --load-privkey "${srcdir}/data/template-test.key" \
+               --load-privkey "${srcdir}/data/privkey1.pem" \
                --template "${srcdir}/templates/template-test.tmpl" \
-               --outfile "${TMPFILE}" --hash $i 2>/dev/null
+               --outfile "${TMPFILE}" --hash $i
 rc=$?
 
 if test -f "${srcdir}/data/template-rsa-$i.pem";then