crypto/x509-utils: Add helper functions for DIAG 508 subcode 1
Introduce helper functions to support signature verification required by DIAG 508 subcode 1: qcrypto_pkcs7_convert_sig_pem() – converts a signature from DER to PEM format qcrypto_x509_verify_sig() – verifies the provided data against the given signature These functions enable basic signature verification support. Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com> Acked-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Farhan Ali <alifm@linux.ibm.com> Reviewed-by: Thomas Huth <thuth@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260730214624.2328883-13-zycai@linux.ibm.com Signed-off-by: Eric Farman <farman@linux.ibm.com>
Zhuoying Cai committed
Jul 30, 2026 at 17:46 UTC
ea691e20cc9b270b9edafd27fc7dea09fcd1f541
2 files changed
+149
crypto/x509-utils.c
+108
@@ -16,6 +16,7 @@
16
#include <gnutls/gnutls.h>
17
#include <gnutls/crypto.h>
18
#include <gnutls/x509.h>
19
+#include <gnutls/pkcs7.h>
20
21
static const int qcrypto_to_gnutls_hash_alg_map[QCRYPTO_HASH_ALGO__MAX] = {
22
[QCRYPTO_HASH_ALGO_MD5] = GNUTLS_DIG_MD5,
@@ -336,6 +337,96 @@ int qcrypto_x509_check_ecc_curve_p521(uint8_t *cert, size_t size, Error **errp)
337
return curve_id == GNUTLS_ECC_CURVE_SECP521R1;
338
}
339
340
+int qcrypto_pkcs7_convert_sig_pem(uint8_t *sig, size_t sig_size,
341
+ uint8_t **result, size_t *resultlen,
342
+ Error **errp)
343
+{
344
+ int ret = -1;
345
+ int rc;
346
+ gnutls_pkcs7_t signature;
347
+ gnutls_datum_t sig_datum_der = {.data = sig, .size = sig_size};
348
+ gnutls_datum_t sig_datum_pem = {.data = NULL, .size = 0};
349
+
350
+ rc = gnutls_pkcs7_init(&signature);
351
+ if (rc < 0) {
352
+ error_setg(errp, "Failed to initialize pkcs7 data: %s", gnutls_strerror(rc));
353
+ return ret;
354
+ }
355
+
356
+ rc = gnutls_pkcs7_import(signature, &sig_datum_der, GNUTLS_X509_FMT_DER);
357
+ if (rc != 0) {
358
+ error_setg(errp, "Failed to import signature: %s", gnutls_strerror(rc));
359
+ goto cleanup;
360
+ }
361
+
362
+ rc = gnutls_pkcs7_export2(signature, GNUTLS_X509_FMT_PEM, &sig_datum_pem);
363
+ if (rc != 0) {
364
+ error_setg(errp, "Failed to convert signature to PEM format: %s",
365
+ gnutls_strerror(rc));
366
+ goto cleanup;
367
+ }
368
+
369
+ *resultlen = sig_datum_pem.size;
370
+ *result = g_memdup2(sig_datum_pem.data, sig_datum_pem.size);
371
+
372
+ ret = 0;
373
+
374
+cleanup:
375
+ gnutls_pkcs7_deinit(signature);
376
+ g_free(sig_datum_pem.data);
377
+ return ret;
378
+}
379
+
380
+int qcrypto_x509_verify_sig(uint8_t *cert, size_t cert_size,
381
+ uint8_t *comp, size_t comp_size,
382
+ uint8_t *sig, size_t sig_size, Error **errp)
383
+{
384
+ int rc;
385
+ int ret = -1;
386
+ gnutls_x509_crt_t crt = NULL;
387
+ gnutls_pkcs7_t signature = NULL;
388
+ gnutls_datum_t cert_datum = {.data = cert, .size = cert_size};
389
+ gnutls_datum_t data_datum = {.data = comp, .size = comp_size};
390
+ gnutls_datum_t sig_datum = {.data = sig, .size = sig_size};
391
+
392
+ rc = gnutls_x509_crt_init(&crt);
393
+ if (rc < 0) {
394
+ error_setg(errp, "Failed to initialize certificate: %s", gnutls_strerror(rc));
395
+ goto cleanup;
396
+ }
397
+
398
+ rc = gnutls_x509_crt_import(crt, &cert_datum, GNUTLS_X509_FMT_PEM);
399
+ if (rc != 0) {
400
+ error_setg(errp, "Failed to import certificate: %s", gnutls_strerror(rc));
401
+ goto cleanup;
402
+ }
403
+
404
+ rc = gnutls_pkcs7_init(&signature);
405
+ if (rc < 0) {
406
+ error_setg(errp, "Failed to initialize pkcs7 data: %s", gnutls_strerror(rc));
407
+ goto cleanup;
408
+ }
409
+
410
+ rc = gnutls_pkcs7_import(signature, &sig_datum, GNUTLS_X509_FMT_PEM);
411
+ if (rc != 0) {
412
+ error_setg(errp, "Failed to import signature: %s", gnutls_strerror(rc));
413
+ goto cleanup;
414
+ }
415
+
416
+ rc = gnutls_pkcs7_verify_direct(signature, crt, 0, &data_datum, 0);
417
+ if (rc != 0) {
418
+ error_setg(errp, "Failed to verify signature: %s", gnutls_strerror(rc));
419
+ goto cleanup;
420
+ }
421
+
422
+ ret = 0;
423
+
424
+cleanup:
425
+ gnutls_x509_crt_deinit(crt);
426
+ gnutls_pkcs7_deinit(signature);
427
+ return ret;
428
+}
429
+
430
#else /* ! CONFIG_GNUTLS */
431
432
int qcrypto_get_x509_cert_fingerprint(uint8_t *cert, size_t size,
@@ -379,4 +470,21 @@ int qcrypto_x509_check_ecc_curve_p521(uint8_t *cert, size_t size, Error **errp)
470
return -1;
471
}
472
473
+int qcrypto_pkcs7_convert_sig_pem(uint8_t *sig, size_t sig_size,
474
+ uint8_t **result,
475
+ size_t *resultlen,
476
+ Error **errp)
477
+{
478
+ error_setg(errp, "GNUTLS is required to export pkcs7 signature");
479
+ return -1;
480
+}
481
+
482
+int qcrypto_x509_verify_sig(uint8_t *cert, size_t cert_size,
483
+ uint8_t *comp, size_t comp_size,
484
+ uint8_t *sig, size_t sig_size, Error **errp)
485
+{
486
+ error_setg(errp, "GNUTLS is required for signature-verification support");
487
+ return -1;
488
+}
489
+
490
#endif /* ! CONFIG_GNUTLS */
include/crypto/x509-utils.h
+41
@@ -91,4 +91,45 @@ int qcrypto_x509_get_cert_key_id(uint8_t *cert, size_t size,
91
*/
92
int qcrypto_x509_check_ecc_curve_p521(uint8_t *cert, size_t size, Error **errp);
93
94
+/**
95
+ * qcrypto_pkcs7_convert_sig_pem
96
+ * @sig: pointer to the PKCS#7 signature in DER format
97
+ * @sig_size: size of the signature
98
+ * @result: output location for the allocated buffer for the signature in
99
+ * PEM format
100
+ * (the function allocates memory which must be freed by the caller)
101
+ * @resultlen: pointer to the size of the buffer
102
+ * (will be updated with the actual size of the PEM-encoded
103
+ * signature)
104
+ * @errp: error pointer
105
+ *
106
+ * Convert given PKCS#7 @sig from DER to PEM format.
107
+ *
108
+ * Returns: 0 if PEM-encoded signature was successfully stored in @result,
109
+ * -1 on error.
110
+ */
111
+int qcrypto_pkcs7_convert_sig_pem(uint8_t *sig, size_t sig_size,
112
+ uint8_t **result,
113
+ size_t *resultlen,
114
+ Error **errp);
115
+
116
+/**
117
+ * qcrypto_x509_verify_sig
118
+ * @cert: pointer to the raw certificate data
119
+ * @cert_size: size of the certificate
120
+ * @comp: pointer to the component to be verified
121
+ * @comp_size: size of the component
122
+ * @sig: pointer to the signature
123
+ * @sig_size: size of the signature
124
+ * @errp: error pointer
125
+ *
126
+ * Verify the provided @comp against the @sig and @cert.
127
+ *
128
+ * Returns: 0 on success,
129
+ * -1 on error.
130
+ */
131
+int qcrypto_x509_verify_sig(uint8_t *cert, size_t cert_size,
132
+ uint8_t *comp, size_t comp_size,
133
+ uint8_t *sig, size_t sig_size, Error **errp);
134
+
135
#endif