@samitouri / QOSamiQemu / commits / ea691e20cc

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