All of lore.kernel.org
 help / color / mirror / Atom feed
From: Zhuoying Cai <zycai@linux.ibm.com>
To: thuth@redhat.com, berrange@redhat.com,
	richard.henderson@linaro.org, david@redhat.com,
	pbonzini@redhat.com, jrossi@linux.ibm.com, qemu-s390x@nongnu.org,
	qemu-devel@nongnu.org
Cc: walling@linux.ibm.com, jjherne@linux.ibm.com,
	pasic@linux.ibm.com, borntraeger@linux.ibm.com,
	farman@linux.ibm.com, mjrosato@linux.ibm.com, iii@linux.ibm.com,
	zycai@linux.ibm.com
Subject: [PATCH v4 02/28] crypto/x509-utils: Add helper functions for certificate store
Date: Fri, 11 Jul 2025 17:10:38 -0400	[thread overview]
Message-ID: <20250711211105.439554-3-zycai@linux.ibm.com> (raw)
In-Reply-To: <20250711211105.439554-1-zycai@linux.ibm.com>

Introduce new helper functions for x509 certificate, which will be used
by the certificate store:

qcrypto_x509_convert_cert_der() - converts a certificate from PEM to DER format
qcrypto_x509_get_keyid_len() - returns the length of the key ID
qcrypto_x509_get_signature_algorithm() - returns signature algorithm of the certificate

These functions provide support for certificate format conversion and
metadata extraction.

Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
---
 crypto/meson.build          |   5 +-
 crypto/x509-utils.c         | 155 ++++++++++++++++++++++++++++++++++++
 include/crypto/x509-utils.h |  71 +++++++++++++++++
 3 files changed, 227 insertions(+), 4 deletions(-)

diff --git a/crypto/meson.build b/crypto/meson.build
index 735635de1f..0614bfa914 100644
--- a/crypto/meson.build
+++ b/crypto/meson.build
@@ -22,12 +22,9 @@ crypto_ss.add(files(
   'tlscredsx509.c',
   'tlssession.c',
   'rsakey.c',
+  'x509-utils.c',
 ))
 
-if gnutls.found()
-  crypto_ss.add(files('x509-utils.c'))
-endif
-
 if nettle.found()
   crypto_ss.add(nettle, files('hash-nettle.c', 'hmac-nettle.c', 'pbkdf-nettle.c'))
   if hogweed.found()
diff --git a/crypto/x509-utils.c b/crypto/x509-utils.c
index 8bad00a51b..d2cf790d5b 100644
--- a/crypto/x509-utils.c
+++ b/crypto/x509-utils.c
@@ -11,6 +11,8 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "crypto/x509-utils.h"
+
+#ifdef CONFIG_GNUTLS
 #include <gnutls/gnutls.h>
 #include <gnutls/crypto.h>
 #include <gnutls/x509.h>
@@ -25,6 +27,87 @@ static const int qcrypto_to_gnutls_hash_alg_map[QCRYPTO_HASH_ALGO__MAX] = {
     [QCRYPTO_HASH_ALGO_RIPEMD160] = GNUTLS_DIG_RMD160,
 };
 
+static const int qcrypto_to_gnutls_keyid_flags_map[] = {
+    [QCRYPTO_KEYID_FLAGS_SHA1] = GNUTLS_KEYID_USE_SHA1,
+    [QCRYPTO_KEYID_FLAGS_SHA256] = GNUTLS_KEYID_USE_SHA256,
+    [QCRYPTO_KEYID_FLAGS_SHA512] = GNUTLS_KEYID_USE_SHA512,
+    [QCRYPTO_KEYID_FLAGS_BEST_KNOWN] = GNUTLS_KEYID_USE_BEST_KNOWN,
+};
+
+static const int gnutls_to_qcrypto_sig_alg_map[] = {
+    [GNUTLS_SIGN_UNKNOWN] = QCRYPTO_SIG_ALGO_UNKNOWN,
+    [GNUTLS_SIGN_RSA_SHA1] = QCRYPTO_SIG_ALGO_RSA_SHA1,
+    [GNUTLS_SIGN_RSA_SHA] = QCRYPTO_SIG_ALGO_RSA_SHA1,
+    [GNUTLS_SIGN_DSA_SHA1] = QCRYPTO_SIG_ALGO_DSA_SHA1,
+    [GNUTLS_SIGN_RSA_MD5] = QCRYPTO_SIG_ALGO_RSA_MD5,
+    [GNUTLS_SIGN_RSA_MD2] = QCRYPTO_SIG_ALGO_RSA_MD2,
+    [GNUTLS_SIGN_RSA_RMD160] = QCRYPTO_SIG_ALGO_RSA_RMD160,
+    [GNUTLS_SIGN_RSA_SHA256] = QCRYPTO_SIG_ALGO_RSA_SHA256,
+    [GNUTLS_SIGN_RSA_SHA384] = QCRYPTO_SIG_ALGO_RSA_SHA384,
+    [GNUTLS_SIGN_RSA_SHA512] = QCRYPTO_SIG_ALGO_RSA_SHA512,
+    [GNUTLS_SIGN_RSA_SHA224] = QCRYPTO_SIG_ALGO_RSA_SHA224,
+    [GNUTLS_SIGN_DSA_SHA224] = QCRYPTO_SIG_ALGO_DSA_SHA224,
+    [GNUTLS_SIGN_DSA_SHA256] = QCRYPTO_SIG_ALGO_DSA_SHA256,
+    [GNUTLS_SIGN_ECDSA_SHA1] = QCRYPTO_SIG_ALGO_ECDSA_SHA1,
+    [GNUTLS_SIGN_ECDSA_SHA224] = QCRYPTO_SIG_ALGO_ECDSA_SHA224,
+    [GNUTLS_SIGN_ECDSA_SHA256] = QCRYPTO_SIG_ALGO_ECDSA_SHA256,
+    [GNUTLS_SIGN_ECDSA_SHA384] = QCRYPTO_SIG_ALGO_ECDSA_SHA384,
+    [GNUTLS_SIGN_ECDSA_SHA512] = QCRYPTO_SIG_ALGO_ECDSA_SHA512,
+};
+
+int qcrypto_x509_convert_cert_der(uint8_t *cert, size_t size,
+                                  uint8_t **result, size_t *resultlen,
+                                  Error **errp)
+{
+    int ret = -1;
+    int rc;
+    gnutls_x509_crt_t crt;
+    gnutls_datum_t datum = {.data = cert, .size = size};
+
+    rc = gnutls_x509_crt_init(&crt);
+    if (rc < 0) {
+        error_setg(errp, "Failed to initialize certificate: %s", gnutls_strerror(rc));
+        return ret;
+    }
+
+    rc = gnutls_x509_crt_import(crt, &datum, GNUTLS_X509_FMT_PEM);
+    if (rc != 0) {
+        error_setg(errp, "Failed to import certificate: %s", gnutls_strerror(rc));
+        goto cleanup;
+    }
+
+    *result = g_malloc0(*resultlen);
+    rc = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, *result, resultlen);
+    if (rc != 0) {
+        error_setg(errp, "Failed to convert certificate to DER format: %s",
+                   gnutls_strerror(rc));
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    gnutls_x509_crt_deinit(crt);
+    return ret;
+}
+
+int qcrypto_x509_get_keyid_len(QCryptoKeyidFlags flag, Error **errp)
+{
+    if (flag >= G_N_ELEMENTS(qcrypto_to_gnutls_keyid_flags_map)) {
+        error_setg(errp, "Unknow key ID flag %d", flag);
+        return -1;
+    }
+
+    if ((flag & qcrypto_to_gnutls_keyid_flags_map[QCRYPTO_KEYID_FLAGS_SHA512]) ||
+        (flag & qcrypto_to_gnutls_keyid_flags_map[QCRYPTO_KEYID_FLAGS_BEST_KNOWN])) {
+        return QCRYPTO_HASH_DIGEST_LEN_SHA512;
+    } else if (flag & qcrypto_to_gnutls_keyid_flags_map[QCRYPTO_KEYID_FLAGS_SHA256]) {
+        return QCRYPTO_HASH_DIGEST_LEN_SHA256;
+    } else {
+        return QCRYPTO_HASH_DIGEST_LEN_SHA1;
+    }
+}
+
 int qcrypto_get_x509_cert_fingerprint(uint8_t *cert, size_t size,
                                       QCryptoHashAlgo alg,
                                       uint8_t *result,
@@ -74,3 +157,75 @@ int qcrypto_get_x509_cert_fingerprint(uint8_t *cert, size_t size,
     gnutls_x509_crt_deinit(crt);
     return ret;
 }
+
+int qcrypto_x509_get_signature_algorithm(uint8_t *cert, size_t size, Error **errp)
+{
+    int rc;
+    int ret = -1;
+    gnutls_x509_crt_t crt;
+    gnutls_datum_t datum = {.data = cert, .size = size};
+
+    rc = gnutls_x509_crt_init(&crt);
+    if (rc < 0) {
+        error_setg(errp, "Failed to initialize certificate: %s", gnutls_strerror(rc));
+        return ret;
+    }
+
+    rc = gnutls_x509_crt_import(crt, &datum, GNUTLS_X509_FMT_PEM);
+    if (rc != 0) {
+        error_setg(errp, "Failed to import certificate: %s", gnutls_strerror(rc));
+        goto cleanup;
+    }
+
+    /*
+     * This function never returns a negative error code.
+     * Error cases and unknown/unsupported signature algorithms
+     * are mapped to GNUTLS_SIGN_UNKNOWN.
+     */
+    rc = gnutls_x509_crt_get_signature_algorithm(crt);
+    if (rc >= G_N_ELEMENTS(gnutls_to_qcrypto_sig_alg_map)) {
+        error_setg(errp, "Unknown signature algorithm %d", rc);
+        goto cleanup;
+    }
+
+    ret = gnutls_to_qcrypto_sig_alg_map[rc];
+
+cleanup:
+    gnutls_x509_crt_deinit(crt);
+    return ret;
+}
+
+#else /* ! CONFIG_GNUTLS */
+
+int qcrypto_x509_convert_cert_der(uint8_t *cert, size_t size,
+                                  uint8_t **result,
+                                  size_t *resultlen,
+                                  Error **errp)
+{
+    error_setg(errp, "GNUTLS is required to export X.509 certificate");
+    return -1;
+}
+
+int qcrypto_x509_get_keyid_len(QCryptoKeyidFlags flag, Error **errp)
+{
+    error_setg(errp, "GNUTLS is required to get key ID length");
+    return -1;
+}
+
+int qcrypto_get_x509_cert_fingerprint(uint8_t *cert, size_t size,
+                                      QCryptoHashAlgo hash,
+                                      uint8_t *result,
+                                      size_t *resultlen,
+                                      Error **errp)
+{
+    error_setg(errp, "GNUTLS is required to get fingerprint");
+    return -1;
+}
+
+int qcrypto_x509_get_signature_algorithm(uint8_t *cert, size_t size, Error **errp)
+{
+    error_setg(errp, "GNUTLS is required to get signature algorithm");
+    return -1;
+}
+
+#endif /* ! CONFIG_GNUTLS */
diff --git a/include/crypto/x509-utils.h b/include/crypto/x509-utils.h
index 1e99661a71..d916d248bb 100644
--- a/include/crypto/x509-utils.h
+++ b/include/crypto/x509-utils.h
@@ -13,10 +13,81 @@
 
 #include "crypto/hash.h"
 
+typedef enum {
+    QCRYPTO_KEYID_FLAGS_SHA1,
+    QCRYPTO_KEYID_FLAGS_SHA256,
+    QCRYPTO_KEYID_FLAGS_SHA512,
+    QCRYPTO_KEYID_FLAGS_BEST_KNOWN,
+} QCryptoKeyidFlags;
+
+typedef enum {
+    QCRYPTO_SIG_ALGO_UNKNOWN,
+    QCRYPTO_SIG_ALGO_RSA_SHA1,
+    QCRYPTO_SIG_ALGO_DSA_SHA1,
+    QCRYPTO_SIG_ALGO_RSA_MD5,
+    QCRYPTO_SIG_ALGO_RSA_MD2,
+    QCRYPTO_SIG_ALGO_RSA_RMD160,
+    QCRYPTO_SIG_ALGO_RSA_SHA256,
+    QCRYPTO_SIG_ALGO_RSA_SHA384,
+    QCRYPTO_SIG_ALGO_RSA_SHA512,
+    QCRYPTO_SIG_ALGO_RSA_SHA224,
+    QCRYPTO_SIG_ALGO_DSA_SHA224,
+    QCRYPTO_SIG_ALGO_DSA_SHA256,
+    QCRYPTO_SIG_ALGO_ECDSA_SHA1,
+    QCRYPTO_SIG_ALGO_ECDSA_SHA224,
+    QCRYPTO_SIG_ALGO_ECDSA_SHA256,
+    QCRYPTO_SIG_ALGO_ECDSA_SHA384,
+    QCRYPTO_SIG_ALGO_ECDSA_SHA512,
+} QCryptoSigAlgo;
+
 int qcrypto_get_x509_cert_fingerprint(uint8_t *cert, size_t size,
                                       QCryptoHashAlgo hash,
                                       uint8_t *result,
                                       size_t *resultlen,
                                       Error **errp);
 
+/**
+ * qcrypto_x509_convert_cert_der
+ * @cert: pointer to the raw certificate data in PEM format
+ * @size: size of the certificate
+ * @result: output location for the allocated buffer for the certificate in DER format
+            (the function allocates memory which must be freed by the caller)
+ * @resultlen: pointer to the size of the buffer
+               (will be replaced by the actual size of the DER-encoded certificate)
+ * @errp: error pointer
+ *
+ * Convert given @cert from PEM to DER format.
+ *
+ * Returns: 0 on success,
+ *         -1 on error.
+ */
+int qcrypto_x509_convert_cert_der(uint8_t *cert, size_t size,
+                                  uint8_t **result,
+                                  size_t *resultlen,
+                                  Error **errp);
+
+/**
+ * qcrypto_x509_get_keyid_len
+ * @flag: the key ID flag
+ *
+ * Determine the length of the key ID of the given @flag.
+ *
+ * Returns: the length on success,
+ *          -1 on error.
+ */
+int qcrypto_x509_get_keyid_len(QCryptoKeyidFlags flag, Error **errp);
+
+/**
+ * qcrypto_x509_get_signature_algorithm
+ * @cert: pointer to the raw certificate data
+ * @size: size of the certificate
+ * @errp: error pointer
+ *
+ * Determine the signature algorithm used to sign the @cert.
+ *
+ * Returns: a value from the QCryptoSigAlgo enum on success,
+ *          -1 on error.
+ */
+int qcrypto_x509_get_signature_algorithm(uint8_t *cert, size_t size, Error **errp);
+
 #endif
-- 
2.49.0



  parent reply	other threads:[~2025-07-11 21:18 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-11 21:10 [PATCH v4 00/28] Secure IPL Support for SCSI Scheme of virtio-blk/virtio-scsi Devices Zhuoying Cai
2025-07-11 21:10 ` [PATCH v4 01/28] Add boot-certificates to s390-ccw-virtio machine type option Zhuoying Cai
2025-07-22 15:56   ` Daniel P. Berrangé
2025-07-11 21:10 ` Zhuoying Cai [this message]
2025-07-22 16:06   ` [PATCH v4 02/28] crypto/x509-utils: Add helper functions for certificate store Daniel P. Berrangé
2025-07-11 21:10 ` [PATCH v4 03/28] hw/s390x/ipl: Create " Zhuoying Cai
2025-07-22 16:14   ` Daniel P. Berrangé
2025-07-11 21:10 ` [PATCH v4 04/28] s390x: Guest support for Certificate Store Facility (CS) Zhuoying Cai
2025-07-21 21:30   ` Collin Walling
2025-07-23 20:15     ` Collin Walling
2025-07-11 21:10 ` [PATCH v4 05/28] s390x/diag: Introduce DIAG 320 for certificate store facility Zhuoying Cai
2025-07-21 21:26   ` Collin Walling
2025-07-21 21:39     ` Collin Walling
2025-07-22 21:08       ` Collin Walling
2025-07-23 17:50     ` Eric Farman
2025-07-11 21:10 ` [PATCH v4 06/28] s390x/diag: Refactor address validation check from diag308_parm_check Zhuoying Cai
2025-07-11 21:10 ` [PATCH v4 07/28] s390x/diag: Implement DIAG 320 subcode 1 Zhuoying Cai
2025-07-23 20:17   ` Eric Farman
2025-07-28 22:01     ` Zhuoying Cai
2025-07-23 22:15   ` Collin Walling
2025-07-23 22:20     ` Collin Walling
2025-07-11 21:10 ` [PATCH v4 08/28] crypto/x509-utils: Add helper functions for DIAG 320 subcode 2 Zhuoying Cai
2025-07-22 16:20   ` Daniel P. Berrangé
2025-07-11 21:10 ` [PATCH v4 09/28] s390x/diag: Implement " Zhuoying Cai
2025-07-22 16:23   ` Daniel P. Berrangé
2025-07-28 20:59   ` Collin Walling
2025-07-29 18:18     ` Zhuoying Cai
2025-07-29 18:56       ` Collin Walling
2025-07-11 21:10 ` [PATCH v4 10/28] s390x/diag: Introduce DIAG 508 for secure IPL operations Zhuoying Cai
2025-07-11 21:10 ` [PATCH v4 11/28] crypto/x509-utils: Add helper functions for DIAG 508 subcode 1 Zhuoying Cai
2025-07-22 16:26   ` Daniel P. Berrangé
2025-07-11 21:10 ` [PATCH v4 12/28] s390x/diag: Implement DIAG 508 subcode 1 for signature verification Zhuoying Cai
2025-07-11 21:10 ` [PATCH v4 13/28] pc-bios/s390-ccw: Introduce IPL Information Report Block (IIRB) Zhuoying Cai
2025-07-11 21:10 ` [PATCH v4 14/28] pc-bios/s390-ccw: Define memory for IPLB and convert IPLB to pointers Zhuoying Cai
2025-07-11 21:10 ` [PATCH v4 15/28] hw/s390x/ipl: Add IPIB flags to IPL Parameter Block Zhuoying Cai
2025-07-11 21:10 ` [PATCH v4 16/28] hw/s390x/ipl: Set iplb->len to maximum length of " Zhuoying Cai
2025-07-11 21:10 ` [PATCH v4 17/28] s390x: Guest support for Secure-IPL Facility Zhuoying Cai
2025-07-14 20:33   ` Collin Walling
2025-07-11 21:10 ` [PATCH v4 18/28] pc-bios/s390-ccw: Refactor zipl_run() Zhuoying Cai
2025-07-14 20:53   ` Collin Walling
2025-07-11 21:10 ` [PATCH v4 19/28] pc-bios/s390-ccw: Refactor zipl_load_segment function Zhuoying Cai
2025-07-14 22:10   ` Collin Walling
2025-07-15 15:59     ` Zhuoying Cai
2025-07-15 21:48       ` Collin Walling
2025-07-11 21:10 ` [PATCH v4 20/28] pc-bios/s390-ccw: Add signature verification for secure IPL in audit mode Zhuoying Cai
2025-07-11 22:50   ` Collin Walling
2025-07-14 14:54     ` Jared Rossi
2025-07-14 15:34       ` Thomas Huth
2025-07-14 17:46         ` Collin Walling
2025-07-21 21:50     ` Zhuoying Cai
2025-07-28 21:05       ` Collin Walling
2025-07-11 21:10 ` [PATCH v4 21/28] s390x: Guest support for Secure-IPL Code Loading Attributes Facility (SCLAF) Zhuoying Cai
2025-07-14 22:13   ` Collin Walling
2025-07-11 21:10 ` [PATCH v4 22/28] pc-bios/s390-ccw: Add additional security checks for secure boot Zhuoying Cai
2025-07-11 21:10 ` [PATCH v4 23/28] Add secure-boot to s390-ccw-virtio machine type option Zhuoying Cai
2025-07-11 21:11 ` [PATCH v4 24/28] hw/s390x/ipl: Set IPIB flags for secure IPL Zhuoying Cai
2025-07-11 21:11 ` [PATCH v4 25/28] pc-bios/s390-ccw: Handle true secure IPL mode Zhuoying Cai
2025-07-11 21:11 ` [PATCH v4 26/28] pc-bios/s390-ccw: Handle secure boot with multiple boot devices Zhuoying Cai
2025-07-22 16:28   ` Daniel P. Berrangé
2025-07-11 21:11 ` [PATCH v4 27/28] hw/s390x/ipl: Handle secure boot without specifying a boot device Zhuoying Cai
2025-07-11 21:11 ` [PATCH v4 28/28] docs: Add secure IPL documentation Zhuoying Cai
2025-07-21 19:13   ` Collin Walling

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250711211105.439554-3-zycai@linux.ibm.com \
    --to=zycai@linux.ibm.com \
    --cc=berrange@redhat.com \
    --cc=borntraeger@linux.ibm.com \
    --cc=david@redhat.com \
    --cc=farman@linux.ibm.com \
    --cc=iii@linux.ibm.com \
    --cc=jjherne@linux.ibm.com \
    --cc=jrossi@linux.ibm.com \
    --cc=mjrosato@linux.ibm.com \
    --cc=pasic@linux.ibm.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-s390x@nongnu.org \
    --cc=richard.henderson@linaro.org \
    --cc=thuth@redhat.com \
    --cc=walling@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.