mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'next-pr-pull-request' of https://gitlab.com/berrange/qemu into staging
Merge crypto and other misc fixes / features * Increase minimum gnutls to 3.7.5 * Increase minimum libgcrypt to 1.9.4 * Increase minimum nettle to 3.7.3 * Drop obsolete in-tree XTS impl * Fix memory leak when loading certificates * Remove/reduce duplication when loading certifcates * Fix possible crash when certificates are unloaded while an active TLS connection is using when in a TLS handshake operation * Deprecate use of dh-params.pem file * Document how to create certificates with Post-Quantum Cryptography compliant algorithms. * Support loading multiple certificate identities to allow support for Post-Quantum crypto in parallel with traditional RSA/ECC * Add "-run-with exit-with-parent=on" parameter * Flush pending errors when seeing ENOBUFS with a zero-copy send attempt * Fix data buffer parameters in hash & IO channel APIs to use 'void *' # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEE2vOm/bJrYpEtDo4/vobrtBUQT98FAmkIr/8ACgkQvobrtBUQ # T9+2RhAAhEak/krdlTJw8OlJonUop7G5mlLU2TEoX0duRORcFhScsdSwb2pyc/wM # tnwfWXsnsKFItJx1y3STkOICtdNqizGoU3+c7wl4anQBurydu+XTs4ESBtVJtMYr # 1lTYvp0HFyKvaXwDWKE+ztltlJiog51tHPDLUIBCnyJysLVqxCHMHmkbG46IPBZo # A2XXxp3j/VBPmhls0JHpbAD4iVE3PChdK7zhyeGe/rld9+0JA12EPCvZ5Uokdj41 # aYP/okvnVH1atucoygPdDE3P5GYBKaSXZUWqzfkKhU7FgaF2863Td7ff1ip+WyWN # FFPNEU1hVg+T5hfsZVQmmIFDdSJWqoZaZM/WJVYdrRY4dKUCPnJ9OINbbnhuWz5E # JFmZOPibRZKQ44XcHX49JRfJEBvoq1z9OT1r7HkEP4D9/O7V/riIunbAESMk0sgi # 0/fatvdhNKMN6YBQM3mtN3yNOcfRSWFtSy9XS9zDjdpEKT7ui2t9FC0ZNSP0FRkS # aTY31FyacjHwU3zaoh6NoqqpxV9wwHrgsJwNbA/IztjmX/jvGG0Gb/sXVEqM59tR # e3VWTmlmZ1T8OLImh1hG4t+nY+XzI64QpVX8H9RCGm21o28DyTcOnTFK4OyIfWe5 # ttnNfEJN8WCVCsA8tcM8yAbZ/0qXrYfiZSO7hq79wE7LvyholAQ= # =9ESG # -----END PGP SIGNATURE----- # gpg: Signature made Mon 03 Nov 2025 02:37:03 PM CET # gpg: using RSA key DAF3A6FDB26B62912D0E8E3FBE86EBB415104FDF # gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>" [unknown] # gpg: aka "Daniel P. Berrange <berrange@redhat.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: DAF3 A6FD B26B 6291 2D0E 8E3F BE86 EBB4 1510 4FDF * tag 'next-pr-pull-request' of https://gitlab.com/berrange/qemu: (32 commits) docs: creation of x509 certs compliant with post-quantum crypto crypto: support upto 5 parallel certificate identities crypto: expand logic to cope with multiple certificate identities crypto: avoid loading the identity certs twice crypto: avoid loading the CA certs twice crypto: deprecate use of external dh-params.pem file crypto: make TLS credentials structs private crypto: fix lifecycle handling of gnutls credentials objects crypto: introduce a wrapper around gnutls credentials crypto: introduce method for reloading TLS creds crypto: reduce duplication in handling TLS priority strings crypto: remove duplication loading x509 CA cert crypto: shorten the endpoint == server check in TLS creds crypto: move release of DH parameters into TLS creds parent crypto: remove needless indirection via parent_obj field crypto: use g_autofree when loading x509 credentials crypto: move check for TLS creds 'dir' property crypto: remove redundant access() checks before loading certs crypto: replace stat() with access() for credential checks crypto: add missing free of certs array ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
@@ -23,10 +23,6 @@
|
||||
|
||||
#include <gnutls/crypto.h>
|
||||
|
||||
#if GNUTLS_VERSION_NUMBER >= 0x030608
|
||||
#define QEMU_GNUTLS_XTS
|
||||
#endif
|
||||
|
||||
bool qcrypto_cipher_supports(QCryptoCipherAlgo alg,
|
||||
QCryptoCipherMode mode)
|
||||
{
|
||||
@@ -44,7 +40,6 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgo alg,
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
#ifdef QEMU_GNUTLS_XTS
|
||||
case QCRYPTO_CIPHER_MODE_XTS:
|
||||
switch (alg) {
|
||||
case QCRYPTO_CIPHER_ALGO_AES_128:
|
||||
@@ -53,7 +48,6 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgo alg,
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -241,7 +235,6 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgo alg,
|
||||
int err;
|
||||
|
||||
switch (mode) {
|
||||
#ifdef QEMU_GNUTLS_XTS
|
||||
case QCRYPTO_CIPHER_MODE_XTS:
|
||||
switch (alg) {
|
||||
case QCRYPTO_CIPHER_ALGO_AES_128:
|
||||
@@ -254,7 +247,6 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgo alg,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case QCRYPTO_CIPHER_MODE_ECB:
|
||||
case QCRYPTO_CIPHER_MODE_CBC:
|
||||
|
||||
@@ -18,10 +18,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_QEMU_PRIVATE_XTS
|
||||
#include "crypto/xts.h"
|
||||
#endif
|
||||
|
||||
#include <nettle/nettle-types.h>
|
||||
#include <nettle/aes.h>
|
||||
#include <nettle/des.h>
|
||||
@@ -30,9 +26,7 @@
|
||||
#include <nettle/serpent.h>
|
||||
#include <nettle/twofish.h>
|
||||
#include <nettle/ctr.h>
|
||||
#ifndef CONFIG_QEMU_PRIVATE_XTS
|
||||
#include <nettle/xts.h>
|
||||
#endif
|
||||
#ifdef CONFIG_CRYPTO_SM4
|
||||
#include <nettle/sm4.h>
|
||||
#endif
|
||||
@@ -154,43 +148,6 @@ static const struct QCryptoCipherDriver NAME##_driver_ctr = { \
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_QEMU_PRIVATE_XTS
|
||||
#define DEFINE__XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \
|
||||
static void NAME##_xts_wrape(const void *ctx, size_t length, \
|
||||
uint8_t *dst, const uint8_t *src) \
|
||||
{ \
|
||||
ENCRYPT((const void *)ctx, length, dst, src); \
|
||||
} \
|
||||
static void NAME##_xts_wrapd(const void *ctx, size_t length, \
|
||||
uint8_t *dst, const uint8_t *src) \
|
||||
{ \
|
||||
DECRYPT((const void *)ctx, length, dst, src); \
|
||||
} \
|
||||
static int NAME##_encrypt_xts(QCryptoCipher *cipher, const void *in, \
|
||||
void *out, size_t len, Error **errp) \
|
||||
{ \
|
||||
TYPE *ctx = container_of(cipher, TYPE, base); \
|
||||
if (!qcrypto_length_check(len, BLEN, errp)) { \
|
||||
return -1; \
|
||||
} \
|
||||
xts_encrypt(&ctx->key, &ctx->key_xts, \
|
||||
NAME##_xts_wrape, NAME##_xts_wrapd, \
|
||||
ctx->iv, len, out, in); \
|
||||
return 0; \
|
||||
} \
|
||||
static int NAME##_decrypt_xts(QCryptoCipher *cipher, const void *in, \
|
||||
void *out, size_t len, Error **errp) \
|
||||
{ \
|
||||
TYPE *ctx = container_of(cipher, TYPE, base); \
|
||||
if (!qcrypto_length_check(len, BLEN, errp)) { \
|
||||
return -1; \
|
||||
} \
|
||||
xts_decrypt(&ctx->key, &ctx->key_xts, \
|
||||
NAME##_xts_wrape, NAME##_xts_wrapd, \
|
||||
ctx->iv, len, out, in); \
|
||||
return 0; \
|
||||
}
|
||||
#else
|
||||
#define DEFINE__XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \
|
||||
static int NAME##_encrypt_xts(QCryptoCipher *cipher, const void *in, \
|
||||
void *out, size_t len, Error **errp) \
|
||||
@@ -214,7 +171,6 @@ static int NAME##_decrypt_xts(QCryptoCipher *cipher, const void *in, \
|
||||
ctx->iv, len, out, in); \
|
||||
return 0; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define DEFINE_XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \
|
||||
QEMU_BUILD_BUG_ON(BLEN != XTS_BLOCK_SIZE); \
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ qcrypto_cipher_validate_key_length(QCryptoCipherAlgo alg,
|
||||
#include "cipher-gcrypt.c.inc"
|
||||
#elif defined CONFIG_NETTLE
|
||||
#include "cipher-nettle.c.inc"
|
||||
#elif defined CONFIG_GNUTLS_CRYPTO
|
||||
#elif defined CONFIG_GNUTLS
|
||||
#include "cipher-gnutls.c.inc"
|
||||
#else
|
||||
#include "cipher-stub.c.inc"
|
||||
|
||||
+8
-8
@@ -67,13 +67,13 @@ int qcrypto_hash_bytesv(QCryptoHashAlgo alg,
|
||||
|
||||
|
||||
int qcrypto_hash_bytes(QCryptoHashAlgo alg,
|
||||
const char *buf,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
uint8_t **result,
|
||||
size_t *resultlen,
|
||||
Error **errp)
|
||||
{
|
||||
struct iovec iov = { .iov_base = (char *)buf,
|
||||
struct iovec iov = { .iov_base = (void *)buf,
|
||||
.iov_len = len };
|
||||
return qcrypto_hash_bytesv(alg, &iov, 1, result, resultlen, errp);
|
||||
}
|
||||
@@ -89,11 +89,11 @@ int qcrypto_hash_updatev(QCryptoHash *hash,
|
||||
}
|
||||
|
||||
int qcrypto_hash_update(QCryptoHash *hash,
|
||||
const char *buf,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
Error **errp)
|
||||
{
|
||||
struct iovec iov = { .iov_base = (char *)buf, .iov_len = len };
|
||||
struct iovec iov = { .iov_base = (void *)buf, .iov_len = len };
|
||||
|
||||
return qcrypto_hash_updatev(hash, &iov, 1, errp);
|
||||
}
|
||||
@@ -206,12 +206,12 @@ int qcrypto_hash_digestv(QCryptoHashAlgo alg,
|
||||
}
|
||||
|
||||
int qcrypto_hash_digest(QCryptoHashAlgo alg,
|
||||
const char *buf,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
char **digest,
|
||||
Error **errp)
|
||||
{
|
||||
struct iovec iov = { .iov_base = (char *)buf, .iov_len = len };
|
||||
struct iovec iov = { .iov_base = (void *)buf, .iov_len = len };
|
||||
|
||||
return qcrypto_hash_digestv(alg, &iov, 1, digest, errp);
|
||||
}
|
||||
@@ -237,12 +237,12 @@ int qcrypto_hash_base64v(QCryptoHashAlgo alg,
|
||||
}
|
||||
|
||||
int qcrypto_hash_base64(QCryptoHashAlgo alg,
|
||||
const char *buf,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
char **base64,
|
||||
Error **errp)
|
||||
{
|
||||
struct iovec iov = { .iov_base = (char *)buf, .iov_len = len };
|
||||
struct iovec iov = { .iov_base = (void *)buf, .iov_len = len };
|
||||
|
||||
return qcrypto_hash_base64v(alg, &iov, 1, base64, errp);
|
||||
}
|
||||
|
||||
+4
-4
@@ -28,14 +28,14 @@ int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
|
||||
}
|
||||
|
||||
int qcrypto_hmac_bytes(QCryptoHmac *hmac,
|
||||
const char *buf,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
uint8_t **result,
|
||||
size_t *resultlen,
|
||||
Error **errp)
|
||||
{
|
||||
struct iovec iov = {
|
||||
.iov_base = (char *)buf,
|
||||
.iov_base = (void *)buf,
|
||||
.iov_len = len
|
||||
};
|
||||
|
||||
@@ -70,13 +70,13 @@ int qcrypto_hmac_digestv(QCryptoHmac *hmac,
|
||||
}
|
||||
|
||||
int qcrypto_hmac_digest(QCryptoHmac *hmac,
|
||||
const char *buf,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
char **digest,
|
||||
Error **errp)
|
||||
{
|
||||
struct iovec iov = {
|
||||
.iov_base = (char *)buf,
|
||||
.iov_base = (void *)buf,
|
||||
.iov_len = len
|
||||
};
|
||||
|
||||
|
||||
+5
-5
@@ -25,7 +25,10 @@ crypto_ss.add(files(
|
||||
))
|
||||
|
||||
if gnutls.found()
|
||||
crypto_ss.add(files('x509-utils.c'))
|
||||
crypto_ss.add(files(
|
||||
'tlscredsbox.c',
|
||||
'x509-utils.c',
|
||||
))
|
||||
endif
|
||||
|
||||
if nettle.found()
|
||||
@@ -33,12 +36,9 @@ if nettle.found()
|
||||
if hogweed.found()
|
||||
crypto_ss.add(gmp, hogweed)
|
||||
endif
|
||||
if xts == 'private'
|
||||
crypto_ss.add(files('xts.c'))
|
||||
endif
|
||||
elif gcrypt.found()
|
||||
crypto_ss.add(gcrypt, files('hash-gcrypt.c', 'hmac-gcrypt.c', 'pbkdf-gcrypt.c'))
|
||||
elif gnutls_crypto.found()
|
||||
elif gnutls.found()
|
||||
crypto_ss.add(gnutls, files('hash-gnutls.c', 'hmac-gnutls.c', 'pbkdf-gnutls.c'))
|
||||
else
|
||||
crypto_ss.add(files('hash-glib.c', 'hmac-glib.c', 'pbkdf-stub.c'))
|
||||
|
||||
+51
-28
@@ -22,6 +22,7 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qapi-types-crypto.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "tlscredspriv.h"
|
||||
#include "trace.h"
|
||||
|
||||
@@ -38,22 +39,7 @@ qcrypto_tls_creds_get_dh_params_file(QCryptoTLSCreds *creds,
|
||||
|
||||
trace_qcrypto_tls_creds_load_dh(creds, filename ? filename : "<generated>");
|
||||
|
||||
if (filename == NULL) {
|
||||
ret = gnutls_dh_params_init(dh_params);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Unable to initialize DH parameters: %s",
|
||||
gnutls_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
ret = gnutls_dh_params_generate2(*dh_params, DH_BITS);
|
||||
if (ret < 0) {
|
||||
gnutls_dh_params_deinit(*dh_params);
|
||||
*dh_params = NULL;
|
||||
error_setg(errp, "Unable to generate DH parameters: %s",
|
||||
gnutls_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (filename != NULL) {
|
||||
GError *gerr = NULL;
|
||||
gchar *contents;
|
||||
gsize len;
|
||||
@@ -67,6 +53,10 @@ qcrypto_tls_creds_get_dh_params_file(QCryptoTLSCreds *creds,
|
||||
g_error_free(gerr);
|
||||
return -1;
|
||||
}
|
||||
warn_report_once("Use of an external DH parameters file '%s' is "
|
||||
"deprecated and will be removed in a future release",
|
||||
filename);
|
||||
|
||||
data.data = (unsigned char *)contents;
|
||||
data.size = len;
|
||||
ret = gnutls_dh_params_init(dh_params);
|
||||
@@ -87,12 +77,22 @@ qcrypto_tls_creds_get_dh_params_file(QCryptoTLSCreds *creds,
|
||||
filename, gnutls_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
*dh_params = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
qcrypto_tls_creds_build_path(QCryptoTLSCreds *creds,
|
||||
const char *filename)
|
||||
{
|
||||
return g_strdup_printf("%s/%s", creds->dir, filename);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qcrypto_tls_creds_get_path(QCryptoTLSCreds *creds,
|
||||
const char *filename,
|
||||
@@ -100,21 +100,11 @@ qcrypto_tls_creds_get_path(QCryptoTLSCreds *creds,
|
||||
char **cred,
|
||||
Error **errp)
|
||||
{
|
||||
struct stat sb;
|
||||
int ret = -1;
|
||||
|
||||
if (!creds->dir) {
|
||||
if (required) {
|
||||
error_setg(errp, "Missing 'dir' property value");
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*cred = qcrypto_tls_creds_build_path(creds, filename);
|
||||
|
||||
*cred = g_strdup_printf("%s/%s", creds->dir, filename);
|
||||
|
||||
if (stat(*cred, &sb) < 0) {
|
||||
if (access(*cred, R_OK) < 0) {
|
||||
if (errno == ENOENT && !required) {
|
||||
ret = 0;
|
||||
} else {
|
||||
@@ -256,6 +246,9 @@ qcrypto_tls_creds_finalize(Object *obj)
|
||||
{
|
||||
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
||||
|
||||
#ifdef CONFIG_GNUTLS
|
||||
qcrypto_tls_creds_box_unref(creds->box);
|
||||
#endif
|
||||
g_free(creds->dir);
|
||||
g_free(creds->priority);
|
||||
}
|
||||
@@ -272,6 +265,36 @@ bool qcrypto_tls_creds_check_endpoint(QCryptoTLSCreds *creds,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
char *qcrypto_tls_creds_get_priority(QCryptoTLSCreds *creds)
|
||||
{
|
||||
QCryptoTLSCredsClass *tcc = QCRYPTO_TLS_CREDS_GET_CLASS(creds);
|
||||
const char *priorityBase =
|
||||
creds->priority ? creds->priority : CONFIG_TLS_PRIORITY;
|
||||
|
||||
if (tcc->prioritySuffix) {
|
||||
return g_strdup_printf("%s:%s", priorityBase, tcc->prioritySuffix);
|
||||
} else {
|
||||
return g_strdup(priorityBase);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool qcrypto_tls_creds_reload(QCryptoTLSCreds *creds,
|
||||
Error **errp)
|
||||
{
|
||||
QCryptoTLSCredsClass *credscls = QCRYPTO_TLS_CREDS_GET_CLASS(creds);
|
||||
|
||||
if (credscls->reload) {
|
||||
return credscls->reload(creds, errp);
|
||||
}
|
||||
|
||||
error_setg(errp, "%s does not support reloading credentials",
|
||||
object_get_typename(OBJECT(creds)));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static const TypeInfo qcrypto_tls_creds_info = {
|
||||
.parent = TYPE_OBJECT,
|
||||
.name = TYPE_QCRYPTO_TLS_CREDS,
|
||||
|
||||
+19
-45
@@ -27,15 +27,19 @@
|
||||
#include "trace.h"
|
||||
|
||||
|
||||
struct QCryptoTLSCredsAnon {
|
||||
QCryptoTLSCreds parent_obj;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_GNUTLS
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
|
||||
|
||||
static int
|
||||
qcrypto_tls_creds_anon_load(QCryptoTLSCredsAnon *creds,
|
||||
Error **errp)
|
||||
{
|
||||
g_autoptr(QCryptoTLSCredsBox) box = NULL;
|
||||
g_autofree char *dhparams = NULL;
|
||||
int ret;
|
||||
|
||||
@@ -43,13 +47,16 @@ qcrypto_tls_creds_anon_load(QCryptoTLSCredsAnon *creds,
|
||||
creds->parent_obj.dir ? creds->parent_obj.dir : "<nodir>");
|
||||
|
||||
if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
|
||||
if (qcrypto_tls_creds_get_path(&creds->parent_obj,
|
||||
box = qcrypto_tls_creds_box_new_server(GNUTLS_CRD_ANON);
|
||||
|
||||
if (creds->parent_obj.dir &&
|
||||
qcrypto_tls_creds_get_path(&creds->parent_obj,
|
||||
QCRYPTO_TLS_CREDS_DH_PARAMS,
|
||||
false, &dhparams, errp) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = gnutls_anon_allocate_server_credentials(&creds->data.server);
|
||||
ret = gnutls_anon_allocate_server_credentials(&box->data.anonserver);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Cannot allocate credentials: %s",
|
||||
gnutls_strerror(ret));
|
||||
@@ -57,46 +64,28 @@ qcrypto_tls_creds_anon_load(QCryptoTLSCredsAnon *creds,
|
||||
}
|
||||
|
||||
if (qcrypto_tls_creds_get_dh_params_file(&creds->parent_obj, dhparams,
|
||||
&creds->parent_obj.dh_params,
|
||||
errp) < 0) {
|
||||
&box->dh_params, errp) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
gnutls_anon_set_server_dh_params(creds->data.server,
|
||||
creds->parent_obj.dh_params);
|
||||
if (box->dh_params) {
|
||||
gnutls_anon_set_server_dh_params(box->data.anonserver,
|
||||
box->dh_params);
|
||||
}
|
||||
} else {
|
||||
ret = gnutls_anon_allocate_client_credentials(&creds->data.client);
|
||||
ret = gnutls_anon_allocate_client_credentials(&box->data.anonclient);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Cannot allocate credentials: %s",
|
||||
gnutls_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
creds->parent_obj.box = g_steal_pointer(&box);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_anon_unload(QCryptoTLSCredsAnon *creds)
|
||||
{
|
||||
if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
|
||||
if (creds->data.client) {
|
||||
gnutls_anon_free_client_credentials(creds->data.client);
|
||||
creds->data.client = NULL;
|
||||
}
|
||||
} else {
|
||||
if (creds->data.server) {
|
||||
gnutls_anon_free_server_credentials(creds->data.server);
|
||||
creds->data.server = NULL;
|
||||
}
|
||||
}
|
||||
if (creds->parent_obj.dh_params) {
|
||||
gnutls_dh_params_deinit(creds->parent_obj.dh_params);
|
||||
creds->parent_obj.dh_params = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* ! CONFIG_GNUTLS */
|
||||
|
||||
|
||||
@@ -108,13 +97,6 @@ qcrypto_tls_creds_anon_load(QCryptoTLSCredsAnon *creds G_GNUC_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_anon_unload(QCryptoTLSCredsAnon *creds G_GNUC_UNUSED)
|
||||
{
|
||||
/* nada */
|
||||
}
|
||||
|
||||
|
||||
#endif /* ! CONFIG_GNUTLS */
|
||||
|
||||
|
||||
@@ -127,21 +109,14 @@ qcrypto_tls_creds_anon_complete(UserCreatable *uc, Error **errp)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_anon_finalize(Object *obj)
|
||||
{
|
||||
QCryptoTLSCredsAnon *creds = QCRYPTO_TLS_CREDS_ANON(obj);
|
||||
|
||||
qcrypto_tls_creds_anon_unload(creds);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_anon_class_init(ObjectClass *oc, const void *data)
|
||||
{
|
||||
UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
|
||||
QCryptoTLSCredsClass *tcc = QCRYPTO_TLS_CREDS_CLASS(oc);
|
||||
|
||||
ucc->complete = qcrypto_tls_creds_anon_complete;
|
||||
tcc->prioritySuffix = "+ANON-DH";
|
||||
}
|
||||
|
||||
|
||||
@@ -149,7 +124,6 @@ static const TypeInfo qcrypto_tls_creds_anon_info = {
|
||||
.parent = TYPE_QCRYPTO_TLS_CREDS,
|
||||
.name = TYPE_QCRYPTO_TLS_CREDS_ANON,
|
||||
.instance_size = sizeof(QCryptoTLSCredsAnon),
|
||||
.instance_finalize = qcrypto_tls_creds_anon_finalize,
|
||||
.class_size = sizeof(QCryptoTLSCredsAnonClass),
|
||||
.class_init = qcrypto_tls_creds_anon_class_init,
|
||||
.interfaces = (const InterfaceInfo[]) {
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* QEMU crypto TLS credential support
|
||||
*
|
||||
* Copyright (c) 2025 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "crypto/tlscredsbox.h"
|
||||
#include "qemu/atomic.h"
|
||||
|
||||
|
||||
static QCryptoTLSCredsBox *
|
||||
qcrypto_tls_creds_box_new_impl(int type, bool server)
|
||||
{
|
||||
QCryptoTLSCredsBox *credsbox = g_new0(QCryptoTLSCredsBox, 1);
|
||||
credsbox->ref = 1;
|
||||
credsbox->server = server;
|
||||
credsbox->type = type;
|
||||
return credsbox;
|
||||
}
|
||||
|
||||
|
||||
QCryptoTLSCredsBox *
|
||||
qcrypto_tls_creds_box_new_server(int type)
|
||||
{
|
||||
return qcrypto_tls_creds_box_new_impl(type, true);
|
||||
}
|
||||
|
||||
|
||||
QCryptoTLSCredsBox *
|
||||
qcrypto_tls_creds_box_new_client(int type)
|
||||
{
|
||||
return qcrypto_tls_creds_box_new_impl(type, false);
|
||||
}
|
||||
|
||||
static void qcrypto_tls_creds_box_free(QCryptoTLSCredsBox *credsbox)
|
||||
{
|
||||
switch (credsbox->type) {
|
||||
case GNUTLS_CRD_CERTIFICATE:
|
||||
if (credsbox->data.cert) {
|
||||
gnutls_certificate_free_credentials(credsbox->data.cert);
|
||||
}
|
||||
break;
|
||||
case GNUTLS_CRD_PSK:
|
||||
if (credsbox->server) {
|
||||
if (credsbox->data.pskserver) {
|
||||
gnutls_psk_free_server_credentials(credsbox->data.pskserver);
|
||||
}
|
||||
} else {
|
||||
if (credsbox->data.pskclient) {
|
||||
gnutls_psk_free_client_credentials(credsbox->data.pskclient);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GNUTLS_CRD_ANON:
|
||||
if (credsbox->server) {
|
||||
if (credsbox->data.anonserver) {
|
||||
gnutls_anon_free_server_credentials(credsbox->data.anonserver);
|
||||
}
|
||||
} else {
|
||||
if (credsbox->data.anonclient) {
|
||||
gnutls_anon_free_client_credentials(credsbox->data.anonclient);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
if (credsbox->dh_params) {
|
||||
gnutls_dh_params_deinit(credsbox->dh_params);
|
||||
}
|
||||
|
||||
g_free(credsbox);
|
||||
}
|
||||
|
||||
|
||||
void qcrypto_tls_creds_box_ref(QCryptoTLSCredsBox *credsbox)
|
||||
{
|
||||
uint32_t ref = qatomic_fetch_inc(&credsbox->ref);
|
||||
/* Assert waaay before the integer overflows */
|
||||
g_assert(ref < INT_MAX);
|
||||
}
|
||||
|
||||
|
||||
void qcrypto_tls_creds_box_unref(QCryptoTLSCredsBox *credsbox)
|
||||
{
|
||||
if (!credsbox) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert(credsbox->ref > 0);
|
||||
|
||||
if (qatomic_fetch_dec(&credsbox->ref) == 1) {
|
||||
qcrypto_tls_creds_box_free(credsbox);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* QEMU crypto TLS credential support
|
||||
*
|
||||
* Copyright (c) 2025 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef QCRYPTO_TLSCREDS_BOX_H
|
||||
#define QCRYPTO_TLSCREDS_BOX_H
|
||||
|
||||
#include "qom/object.h"
|
||||
|
||||
#ifdef CONFIG_GNUTLS
|
||||
#include <gnutls/gnutls.h>
|
||||
#endif
|
||||
|
||||
typedef struct QCryptoTLSCredsBox QCryptoTLSCredsBox;
|
||||
|
||||
struct QCryptoTLSCredsBox {
|
||||
uint32_t ref;
|
||||
bool server;
|
||||
int type;
|
||||
union {
|
||||
void *any;
|
||||
#ifdef CONFIG_GNUTLS
|
||||
/*
|
||||
* All of these gnutls_XXXX_credentials_t types are
|
||||
* pointers, hence matching the 'any' field above
|
||||
*/
|
||||
gnutls_anon_server_credentials_t anonserver;
|
||||
gnutls_anon_client_credentials_t anonclient;
|
||||
gnutls_psk_server_credentials_t pskserver;
|
||||
gnutls_psk_client_credentials_t pskclient;
|
||||
gnutls_certificate_credentials_t cert;
|
||||
#endif
|
||||
} data;
|
||||
#ifdef CONFIG_GNUTLS
|
||||
gnutls_dh_params_t dh_params;
|
||||
#endif
|
||||
};
|
||||
|
||||
QCryptoTLSCredsBox *qcrypto_tls_creds_box_new_server(int type);
|
||||
QCryptoTLSCredsBox *qcrypto_tls_creds_box_new_client(int type);
|
||||
void qcrypto_tls_creds_box_ref(QCryptoTLSCredsBox *credsbox);
|
||||
void qcrypto_tls_creds_box_unref(QCryptoTLSCredsBox *credsbox);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoTLSCredsBox, qcrypto_tls_creds_box_unref);
|
||||
|
||||
#endif /* QCRYPTO_TLSCREDS_BOX_H */
|
||||
+5
-33
@@ -22,6 +22,7 @@
|
||||
#define QCRYPTO_TLSCREDSPRIV_H
|
||||
|
||||
#include "crypto/tlscreds.h"
|
||||
#include "crypto/tlscredsbox.h"
|
||||
|
||||
#ifdef CONFIG_GNUTLS
|
||||
#include <gnutls/gnutls.h>
|
||||
@@ -31,45 +32,16 @@ struct QCryptoTLSCreds {
|
||||
Object parent_obj;
|
||||
char *dir;
|
||||
QCryptoTLSCredsEndpoint endpoint;
|
||||
#ifdef CONFIG_GNUTLS
|
||||
gnutls_dh_params_t dh_params;
|
||||
#endif
|
||||
bool verifyPeer;
|
||||
char *priority;
|
||||
};
|
||||
|
||||
struct QCryptoTLSCredsAnon {
|
||||
QCryptoTLSCreds parent_obj;
|
||||
#ifdef CONFIG_GNUTLS
|
||||
union {
|
||||
gnutls_anon_server_credentials_t server;
|
||||
gnutls_anon_client_credentials_t client;
|
||||
} data;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct QCryptoTLSCredsPSK {
|
||||
QCryptoTLSCreds parent_obj;
|
||||
char *username;
|
||||
#ifdef CONFIG_GNUTLS
|
||||
union {
|
||||
gnutls_psk_server_credentials_t server;
|
||||
gnutls_psk_client_credentials_t client;
|
||||
} data;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct QCryptoTLSCredsX509 {
|
||||
QCryptoTLSCreds parent_obj;
|
||||
#ifdef CONFIG_GNUTLS
|
||||
gnutls_certificate_credentials_t data;
|
||||
#endif
|
||||
bool sanityCheck;
|
||||
char *passwordid;
|
||||
QCryptoTLSCredsBox *box;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_GNUTLS
|
||||
|
||||
char *qcrypto_tls_creds_build_path(QCryptoTLSCreds *creds,
|
||||
const char *filename);
|
||||
|
||||
int qcrypto_tls_creds_get_path(QCryptoTLSCreds *creds,
|
||||
const char *filename,
|
||||
bool required,
|
||||
|
||||
+28
-36
@@ -27,6 +27,11 @@
|
||||
#include "trace.h"
|
||||
|
||||
|
||||
struct QCryptoTLSCredsPSK {
|
||||
QCryptoTLSCreds parent_obj;
|
||||
char *username;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_GNUTLS
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
@@ -71,6 +76,7 @@ static int
|
||||
qcrypto_tls_creds_psk_load(QCryptoTLSCredsPSK *creds,
|
||||
Error **errp)
|
||||
{
|
||||
g_autoptr(QCryptoTLSCredsBox) box = NULL;
|
||||
g_autofree char *pskfile = NULL;
|
||||
g_autofree char *dhparams = NULL;
|
||||
const char *username;
|
||||
@@ -81,7 +87,14 @@ qcrypto_tls_creds_psk_load(QCryptoTLSCredsPSK *creds,
|
||||
trace_qcrypto_tls_creds_psk_load(creds,
|
||||
creds->parent_obj.dir ? creds->parent_obj.dir : "<nodir>");
|
||||
|
||||
if (!creds->parent_obj.dir) {
|
||||
error_setg(errp, "Missing 'dir' property value");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
|
||||
box = qcrypto_tls_creds_box_new_server(GNUTLS_CRD_PSK);
|
||||
|
||||
if (creds->username) {
|
||||
error_setg(errp, "username should not be set when endpoint=server");
|
||||
goto cleanup;
|
||||
@@ -96,7 +109,7 @@ qcrypto_tls_creds_psk_load(QCryptoTLSCredsPSK *creds,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = gnutls_psk_allocate_server_credentials(&creds->data.server);
|
||||
ret = gnutls_psk_allocate_server_credentials(&box->data.pskserver);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Cannot allocate credentials: %s",
|
||||
gnutls_strerror(ret));
|
||||
@@ -104,20 +117,25 @@ qcrypto_tls_creds_psk_load(QCryptoTLSCredsPSK *creds,
|
||||
}
|
||||
|
||||
if (qcrypto_tls_creds_get_dh_params_file(&creds->parent_obj, dhparams,
|
||||
&creds->parent_obj.dh_params,
|
||||
&box->dh_params,
|
||||
errp) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = gnutls_psk_set_server_credentials_file(creds->data.server, pskfile);
|
||||
ret = gnutls_psk_set_server_credentials_file(box->data.pskserver,
|
||||
pskfile);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Cannot set PSK server credentials: %s",
|
||||
gnutls_strerror(ret));
|
||||
goto cleanup;
|
||||
}
|
||||
gnutls_psk_set_server_dh_params(creds->data.server,
|
||||
creds->parent_obj.dh_params);
|
||||
if (box->dh_params) {
|
||||
gnutls_psk_set_server_dh_params(box->data.pskserver,
|
||||
box->dh_params);
|
||||
}
|
||||
} else {
|
||||
box = qcrypto_tls_creds_box_new_client(GNUTLS_CRD_PSK);
|
||||
|
||||
if (qcrypto_tls_creds_get_path(&creds->parent_obj,
|
||||
QCRYPTO_TLS_CREDS_PSKFILE,
|
||||
true, &pskfile, errp) < 0) {
|
||||
@@ -133,14 +151,14 @@ qcrypto_tls_creds_psk_load(QCryptoTLSCredsPSK *creds,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = gnutls_psk_allocate_client_credentials(&creds->data.client);
|
||||
ret = gnutls_psk_allocate_client_credentials(&box->data.pskclient);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Cannot allocate credentials: %s",
|
||||
gnutls_strerror(ret));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = gnutls_psk_set_client_credentials(creds->data.client,
|
||||
ret = gnutls_psk_set_client_credentials(box->data.pskclient,
|
||||
username, &key, GNUTLS_PSK_KEY_HEX);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Cannot set PSK client credentials: %s",
|
||||
@@ -148,6 +166,7 @@ qcrypto_tls_creds_psk_load(QCryptoTLSCredsPSK *creds,
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
creds->parent_obj.box = g_steal_pointer(&box);
|
||||
|
||||
rv = 0;
|
||||
cleanup:
|
||||
@@ -155,27 +174,6 @@ qcrypto_tls_creds_psk_load(QCryptoTLSCredsPSK *creds,
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_psk_unload(QCryptoTLSCredsPSK *creds)
|
||||
{
|
||||
if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
|
||||
if (creds->data.client) {
|
||||
gnutls_psk_free_client_credentials(creds->data.client);
|
||||
creds->data.client = NULL;
|
||||
}
|
||||
} else {
|
||||
if (creds->data.server) {
|
||||
gnutls_psk_free_server_credentials(creds->data.server);
|
||||
creds->data.server = NULL;
|
||||
}
|
||||
}
|
||||
if (creds->parent_obj.dh_params) {
|
||||
gnutls_dh_params_deinit(creds->parent_obj.dh_params);
|
||||
creds->parent_obj.dh_params = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* ! CONFIG_GNUTLS */
|
||||
|
||||
|
||||
@@ -187,13 +185,6 @@ qcrypto_tls_creds_psk_load(QCryptoTLSCredsPSK *creds G_GNUC_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_psk_unload(QCryptoTLSCredsPSK *creds G_GNUC_UNUSED)
|
||||
{
|
||||
/* nada */
|
||||
}
|
||||
|
||||
|
||||
#endif /* ! CONFIG_GNUTLS */
|
||||
|
||||
|
||||
@@ -211,7 +202,6 @@ qcrypto_tls_creds_psk_finalize(Object *obj)
|
||||
{
|
||||
QCryptoTLSCredsPSK *creds = QCRYPTO_TLS_CREDS_PSK(obj);
|
||||
|
||||
qcrypto_tls_creds_psk_unload(creds);
|
||||
g_free(creds->username);
|
||||
}
|
||||
|
||||
@@ -239,8 +229,10 @@ static void
|
||||
qcrypto_tls_creds_psk_class_init(ObjectClass *oc, const void *data)
|
||||
{
|
||||
UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
|
||||
QCryptoTLSCredsClass *tcc = QCRYPTO_TLS_CREDS_CLASS(oc);
|
||||
|
||||
ucc->complete = qcrypto_tls_creds_psk_complete;
|
||||
tcc->prioritySuffix = "+ECDHE-PSK:+DHE-PSK:+PSK";
|
||||
|
||||
object_class_property_add_str(oc, "username",
|
||||
qcrypto_tls_creds_psk_prop_get_username,
|
||||
|
||||
+397
-206
File diff suppressed because it is too large
Load Diff
+36
-107
@@ -38,6 +38,7 @@
|
||||
|
||||
struct QCryptoTLSSession {
|
||||
QCryptoTLSCreds *creds;
|
||||
QCryptoTLSCredsBox *credsbox;
|
||||
gnutls_session_t handle;
|
||||
char *hostname;
|
||||
char *authzid;
|
||||
@@ -78,6 +79,7 @@ qcrypto_tls_session_free(QCryptoTLSSession *session)
|
||||
g_free(session->hostname);
|
||||
g_free(session->peername);
|
||||
g_free(session->authzid);
|
||||
qcrypto_tls_creds_box_unref(session->credsbox);
|
||||
object_unref(OBJECT(session->creds));
|
||||
qemu_mutex_destroy(&session->lock);
|
||||
g_free(session);
|
||||
@@ -155,9 +157,6 @@ qcrypto_tls_session_pull(void *opaque, void *buf, size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
#define TLS_PRIORITY_ADDITIONAL_ANON "+ANON-DH"
|
||||
#define TLS_PRIORITY_ADDITIONAL_PSK "+ECDHE-PSK:+DHE-PSK:+PSK"
|
||||
|
||||
QCryptoTLSSession *
|
||||
qcrypto_tls_session_new(QCryptoTLSCreds *creds,
|
||||
const char *hostname,
|
||||
@@ -167,6 +166,7 @@ qcrypto_tls_session_new(QCryptoTLSCreds *creds,
|
||||
{
|
||||
QCryptoTLSSession *session;
|
||||
int ret;
|
||||
g_autofree char *prio = NULL;
|
||||
|
||||
session = g_new0(QCryptoTLSSession, 1);
|
||||
trace_qcrypto_tls_session_new(
|
||||
@@ -200,113 +200,41 @@ qcrypto_tls_session_new(QCryptoTLSCreds *creds,
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (object_dynamic_cast(OBJECT(creds),
|
||||
TYPE_QCRYPTO_TLS_CREDS_ANON)) {
|
||||
QCryptoTLSCredsAnon *acreds = QCRYPTO_TLS_CREDS_ANON(creds);
|
||||
char *prio;
|
||||
|
||||
if (creds->priority != NULL) {
|
||||
prio = g_strdup_printf("%s:%s",
|
||||
creds->priority,
|
||||
TLS_PRIORITY_ADDITIONAL_ANON);
|
||||
} else {
|
||||
prio = g_strdup(CONFIG_TLS_PRIORITY ":"
|
||||
TLS_PRIORITY_ADDITIONAL_ANON);
|
||||
}
|
||||
|
||||
ret = gnutls_priority_set_direct(session->handle, prio, NULL);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Unable to set TLS session priority %s: %s",
|
||||
prio, gnutls_strerror(ret));
|
||||
g_free(prio);
|
||||
goto error;
|
||||
}
|
||||
g_free(prio);
|
||||
if (creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
|
||||
ret = gnutls_credentials_set(session->handle,
|
||||
GNUTLS_CRD_ANON,
|
||||
acreds->data.server);
|
||||
} else {
|
||||
ret = gnutls_credentials_set(session->handle,
|
||||
GNUTLS_CRD_ANON,
|
||||
acreds->data.client);
|
||||
}
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Cannot set session credentials: %s",
|
||||
gnutls_strerror(ret));
|
||||
goto error;
|
||||
}
|
||||
} else if (object_dynamic_cast(OBJECT(creds),
|
||||
TYPE_QCRYPTO_TLS_CREDS_PSK)) {
|
||||
QCryptoTLSCredsPSK *pcreds = QCRYPTO_TLS_CREDS_PSK(creds);
|
||||
char *prio;
|
||||
|
||||
if (creds->priority != NULL) {
|
||||
prio = g_strdup_printf("%s:%s",
|
||||
creds->priority,
|
||||
TLS_PRIORITY_ADDITIONAL_PSK);
|
||||
} else {
|
||||
prio = g_strdup(CONFIG_TLS_PRIORITY ":"
|
||||
TLS_PRIORITY_ADDITIONAL_PSK);
|
||||
}
|
||||
|
||||
ret = gnutls_priority_set_direct(session->handle, prio, NULL);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Unable to set TLS session priority %s: %s",
|
||||
prio, gnutls_strerror(ret));
|
||||
g_free(prio);
|
||||
goto error;
|
||||
}
|
||||
g_free(prio);
|
||||
if (creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
|
||||
ret = gnutls_credentials_set(session->handle,
|
||||
GNUTLS_CRD_PSK,
|
||||
pcreds->data.server);
|
||||
} else {
|
||||
ret = gnutls_credentials_set(session->handle,
|
||||
GNUTLS_CRD_PSK,
|
||||
pcreds->data.client);
|
||||
}
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Cannot set session credentials: %s",
|
||||
gnutls_strerror(ret));
|
||||
goto error;
|
||||
}
|
||||
} else if (object_dynamic_cast(OBJECT(creds),
|
||||
TYPE_QCRYPTO_TLS_CREDS_X509)) {
|
||||
QCryptoTLSCredsX509 *tcreds = QCRYPTO_TLS_CREDS_X509(creds);
|
||||
const char *prio = creds->priority;
|
||||
if (!prio) {
|
||||
prio = CONFIG_TLS_PRIORITY;
|
||||
}
|
||||
|
||||
ret = gnutls_priority_set_direct(session->handle, prio, NULL);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Cannot set default TLS session priority %s: %s",
|
||||
prio, gnutls_strerror(ret));
|
||||
goto error;
|
||||
}
|
||||
ret = gnutls_credentials_set(session->handle,
|
||||
GNUTLS_CRD_CERTIFICATE,
|
||||
tcreds->data);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Cannot set session credentials: %s",
|
||||
gnutls_strerror(ret));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
|
||||
/* This requests, but does not enforce a client cert.
|
||||
* The cert checking code later does enforcement */
|
||||
gnutls_certificate_server_set_request(session->handle,
|
||||
GNUTLS_CERT_REQUEST);
|
||||
}
|
||||
} else {
|
||||
error_setg(errp, "Unsupported TLS credentials type %s",
|
||||
object_get_typename(OBJECT(creds)));
|
||||
prio = qcrypto_tls_creds_get_priority(creds);
|
||||
ret = gnutls_priority_set_direct(session->handle, prio, NULL);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Unable to set TLS session priority %s: %s",
|
||||
prio, gnutls_strerror(ret));
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = gnutls_credentials_set(session->handle,
|
||||
creds->box->type,
|
||||
creds->box->data.any);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Cannot set session credentials: %s",
|
||||
gnutls_strerror(ret));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* creds->box->data.any must be kept alive for as long
|
||||
* as the gnutls_session_t is alive, so acquire a ref
|
||||
*/
|
||||
qcrypto_tls_creds_box_ref(creds->box);
|
||||
session->credsbox = creds->box;
|
||||
|
||||
if (object_dynamic_cast(OBJECT(creds),
|
||||
TYPE_QCRYPTO_TLS_CREDS_X509) &&
|
||||
creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
|
||||
/*
|
||||
* This requests, but does not enforce a client cert.
|
||||
* The cert checking code later does enforcement
|
||||
*/
|
||||
gnutls_certificate_server_set_request(session->handle,
|
||||
GNUTLS_CERT_REQUEST);
|
||||
}
|
||||
|
||||
gnutls_transport_set_ptr(session->handle, session);
|
||||
gnutls_transport_set_push_function(session->handle,
|
||||
qcrypto_tls_session_push);
|
||||
@@ -417,6 +345,7 @@ qcrypto_tls_session_check_certificate(QCryptoTLSSession *session,
|
||||
goto error;
|
||||
}
|
||||
session->peername = (char *)g_steal_pointer(&dname.data);
|
||||
trace_qcrypto_tls_session_check_x509_dn(session, session->peername);
|
||||
if (session->authzid) {
|
||||
bool allow;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ qcrypto_tls_creds_x509_load_cert_list(void *creds, const char *file) "TLS creds
|
||||
# tlssession.c
|
||||
qcrypto_tls_session_new(void *session, void *creds, const char *hostname, const char *authzid, int endpoint) "TLS session new session=%p creds=%p hostname=%s authzid=%s endpoint=%d"
|
||||
qcrypto_tls_session_check_creds(void *session, const char *status) "TLS session check creds session=%p status=%s"
|
||||
qcrypto_tls_session_check_x509_dn(void *session, const char *dname) "TLS session check x509 distinguished name session=%p dname=%s"
|
||||
qcrypto_tls_session_parameters(void *session, int threadSafety, int protocol, int cipher) "TLS session parameters session=%p threadSafety=%d protocol=%d cipher=%d"
|
||||
qcrypto_tls_session_bug1717_workaround(void *session) "TLS session bug1717 workaround session=%p"
|
||||
|
||||
|
||||
-250
@@ -1,250 +0,0 @@
|
||||
/*
|
||||
* QEMU Crypto XTS cipher mode
|
||||
*
|
||||
* Copyright (c) 2015-2016 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This code is originally derived from public domain / WTFPL code in
|
||||
* LibTomCrypt crytographic library http://libtom.org. The XTS code
|
||||
* was donated by Elliptic Semiconductor Inc (www.ellipticsemi.com)
|
||||
* to the LibTom Projects
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/bswap.h"
|
||||
#include "crypto/xts.h"
|
||||
|
||||
typedef union {
|
||||
uint8_t b[XTS_BLOCK_SIZE];
|
||||
uint64_t u[2];
|
||||
} xts_uint128;
|
||||
|
||||
static inline void xts_uint128_xor(xts_uint128 *D,
|
||||
const xts_uint128 *S1,
|
||||
const xts_uint128 *S2)
|
||||
{
|
||||
D->u[0] = S1->u[0] ^ S2->u[0];
|
||||
D->u[1] = S1->u[1] ^ S2->u[1];
|
||||
}
|
||||
|
||||
static inline void xts_uint128_cpu_to_les(xts_uint128 *v)
|
||||
{
|
||||
cpu_to_le64s(&v->u[0]);
|
||||
cpu_to_le64s(&v->u[1]);
|
||||
}
|
||||
|
||||
static inline void xts_uint128_le_to_cpus(xts_uint128 *v)
|
||||
{
|
||||
le64_to_cpus(&v->u[0]);
|
||||
le64_to_cpus(&v->u[1]);
|
||||
}
|
||||
|
||||
static void xts_mult_x(xts_uint128 *I)
|
||||
{
|
||||
uint64_t tt;
|
||||
|
||||
xts_uint128_le_to_cpus(I);
|
||||
|
||||
tt = I->u[0] >> 63;
|
||||
I->u[0] <<= 1;
|
||||
|
||||
if (I->u[1] >> 63) {
|
||||
I->u[0] ^= 0x87;
|
||||
}
|
||||
I->u[1] <<= 1;
|
||||
I->u[1] |= tt;
|
||||
|
||||
xts_uint128_cpu_to_les(I);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* xts_tweak_encdec:
|
||||
* @param ctxt: the cipher context
|
||||
* @param func: the cipher function
|
||||
* @src: buffer providing the input text of XTS_BLOCK_SIZE bytes
|
||||
* @dst: buffer to output the output text of XTS_BLOCK_SIZE bytes
|
||||
* @iv: the initialization vector tweak of XTS_BLOCK_SIZE bytes
|
||||
*
|
||||
* Encrypt/decrypt data with a tweak
|
||||
*/
|
||||
static inline void xts_tweak_encdec(const void *ctx,
|
||||
xts_cipher_func *func,
|
||||
const xts_uint128 *src,
|
||||
xts_uint128 *dst,
|
||||
xts_uint128 *iv)
|
||||
{
|
||||
/* tweak encrypt block i */
|
||||
xts_uint128_xor(dst, src, iv);
|
||||
|
||||
func(ctx, XTS_BLOCK_SIZE, dst->b, dst->b);
|
||||
|
||||
xts_uint128_xor(dst, dst, iv);
|
||||
|
||||
/* LFSR the tweak */
|
||||
xts_mult_x(iv);
|
||||
}
|
||||
|
||||
|
||||
void xts_decrypt(const void *datactx,
|
||||
const void *tweakctx,
|
||||
xts_cipher_func *encfunc,
|
||||
xts_cipher_func *decfunc,
|
||||
uint8_t *iv,
|
||||
size_t length,
|
||||
uint8_t *dst,
|
||||
const uint8_t *src)
|
||||
{
|
||||
xts_uint128 PP, CC, T;
|
||||
unsigned long i, m, mo, lim;
|
||||
|
||||
/* get number of blocks */
|
||||
m = length >> 4;
|
||||
mo = length & 15;
|
||||
|
||||
/* must have at least one full block */
|
||||
g_assert(m != 0);
|
||||
|
||||
if (mo == 0) {
|
||||
lim = m;
|
||||
} else {
|
||||
lim = m - 1;
|
||||
}
|
||||
|
||||
/* encrypt the iv */
|
||||
encfunc(tweakctx, XTS_BLOCK_SIZE, T.b, iv);
|
||||
|
||||
if (QEMU_PTR_IS_ALIGNED(src, sizeof(uint64_t)) &&
|
||||
QEMU_PTR_IS_ALIGNED(dst, sizeof(uint64_t))) {
|
||||
xts_uint128 *S = (xts_uint128 *)src;
|
||||
xts_uint128 *D = (xts_uint128 *)dst;
|
||||
for (i = 0; i < lim; i++, S++, D++) {
|
||||
xts_tweak_encdec(datactx, decfunc, S, D, &T);
|
||||
}
|
||||
} else {
|
||||
xts_uint128 D;
|
||||
|
||||
for (i = 0; i < lim; i++) {
|
||||
memcpy(&D, src, XTS_BLOCK_SIZE);
|
||||
xts_tweak_encdec(datactx, decfunc, &D, &D, &T);
|
||||
memcpy(dst, &D, XTS_BLOCK_SIZE);
|
||||
src += XTS_BLOCK_SIZE;
|
||||
dst += XTS_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/* if length is not a multiple of XTS_BLOCK_SIZE then */
|
||||
if (mo > 0) {
|
||||
xts_uint128 S, D;
|
||||
memcpy(&CC, &T, XTS_BLOCK_SIZE);
|
||||
xts_mult_x(&CC);
|
||||
|
||||
/* PP = tweak decrypt block m-1 */
|
||||
memcpy(&S, src, XTS_BLOCK_SIZE);
|
||||
xts_tweak_encdec(datactx, decfunc, &S, &PP, &CC);
|
||||
|
||||
/* Pm = first length % XTS_BLOCK_SIZE bytes of PP */
|
||||
for (i = 0; i < mo; i++) {
|
||||
CC.b[i] = src[XTS_BLOCK_SIZE + i];
|
||||
dst[XTS_BLOCK_SIZE + i] = PP.b[i];
|
||||
}
|
||||
for (; i < XTS_BLOCK_SIZE; i++) {
|
||||
CC.b[i] = PP.b[i];
|
||||
}
|
||||
|
||||
/* Pm-1 = Tweak uncrypt CC */
|
||||
xts_tweak_encdec(datactx, decfunc, &CC, &D, &T);
|
||||
memcpy(dst, &D, XTS_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
/* Decrypt the iv back */
|
||||
decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T.b);
|
||||
}
|
||||
|
||||
|
||||
void xts_encrypt(const void *datactx,
|
||||
const void *tweakctx,
|
||||
xts_cipher_func *encfunc,
|
||||
xts_cipher_func *decfunc,
|
||||
uint8_t *iv,
|
||||
size_t length,
|
||||
uint8_t *dst,
|
||||
const uint8_t *src)
|
||||
{
|
||||
xts_uint128 PP, CC, T;
|
||||
unsigned long i, m, mo, lim;
|
||||
|
||||
/* get number of blocks */
|
||||
m = length >> 4;
|
||||
mo = length & 15;
|
||||
|
||||
/* must have at least one full block */
|
||||
g_assert(m != 0);
|
||||
|
||||
if (mo == 0) {
|
||||
lim = m;
|
||||
} else {
|
||||
lim = m - 1;
|
||||
}
|
||||
|
||||
/* encrypt the iv */
|
||||
encfunc(tweakctx, XTS_BLOCK_SIZE, T.b, iv);
|
||||
|
||||
if (QEMU_PTR_IS_ALIGNED(src, sizeof(uint64_t)) &&
|
||||
QEMU_PTR_IS_ALIGNED(dst, sizeof(uint64_t))) {
|
||||
xts_uint128 *S = (xts_uint128 *)src;
|
||||
xts_uint128 *D = (xts_uint128 *)dst;
|
||||
for (i = 0; i < lim; i++, S++, D++) {
|
||||
xts_tweak_encdec(datactx, encfunc, S, D, &T);
|
||||
}
|
||||
} else {
|
||||
xts_uint128 D;
|
||||
|
||||
for (i = 0; i < lim; i++) {
|
||||
memcpy(&D, src, XTS_BLOCK_SIZE);
|
||||
xts_tweak_encdec(datactx, encfunc, &D, &D, &T);
|
||||
memcpy(dst, &D, XTS_BLOCK_SIZE);
|
||||
|
||||
dst += XTS_BLOCK_SIZE;
|
||||
src += XTS_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/* if length is not a multiple of XTS_BLOCK_SIZE then */
|
||||
if (mo > 0) {
|
||||
xts_uint128 S, D;
|
||||
/* CC = tweak encrypt block m-1 */
|
||||
memcpy(&S, src, XTS_BLOCK_SIZE);
|
||||
xts_tweak_encdec(datactx, encfunc, &S, &CC, &T);
|
||||
|
||||
/* Cm = first length % XTS_BLOCK_SIZE bytes of CC */
|
||||
for (i = 0; i < mo; i++) {
|
||||
PP.b[i] = src[XTS_BLOCK_SIZE + i];
|
||||
dst[XTS_BLOCK_SIZE + i] = CC.b[i];
|
||||
}
|
||||
|
||||
for (; i < XTS_BLOCK_SIZE; i++) {
|
||||
PP.b[i] = CC.b[i];
|
||||
}
|
||||
|
||||
/* Cm-1 = Tweak encrypt PP */
|
||||
xts_tweak_encdec(datactx, encfunc, &PP, &D, &T);
|
||||
memcpy(dst, &D, XTS_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
/* Decrypt the iv back */
|
||||
decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T.b);
|
||||
}
|
||||
@@ -385,6 +385,15 @@ Options are:
|
||||
- move backing file to NVDIMM storage and keep ``pmem=on``
|
||||
(to have NVDIMM with persistence guaranties).
|
||||
|
||||
Using an external DH (Diffie-Hellman) parameters file (since 10.2)
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
Loading of external Diffie-Hellman parameters from a 'dh-params.pem'
|
||||
file is deprecated and will be removed with no replacement in a
|
||||
future release. Where no 'dh-params.pem' file is provided, the DH
|
||||
parameters will be automatically negotiated in accordance with
|
||||
RFC7919.
|
||||
|
||||
Device options
|
||||
--------------
|
||||
|
||||
|
||||
+127
-7
@@ -36,8 +36,58 @@ server and exposing it directly to remote browser clients. In such a
|
||||
case it might be useful to use a commercial CA to avoid needing to
|
||||
install custom CA certs in the web browsers.
|
||||
|
||||
The recommendation is for the server to keep its certificates in either
|
||||
``/etc/pki/qemu`` or for unprivileged users in ``$HOME/.pki/qemu``.
|
||||
.. _tls_cert_file_naming:
|
||||
|
||||
Certificate file naming
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In a simple setup, where all QEMU instances on a machine share the
|
||||
same TLS configuration, it is suggested that QEMU certificates be
|
||||
kept in either ``/etc/pki/qemu`` or, for unprivileged users, in
|
||||
``$HOME/.pki/qemu``. Where different QEMU subsystems require
|
||||
different certificate configurations, sub-dirs of these locations
|
||||
may be chosen.
|
||||
|
||||
The default file names that QEMU will traditionally load are:
|
||||
|
||||
* ``ca-cert.pem`` - mandatory; for both client and server configurations
|
||||
* ``ca-crl.pem`` - optional; for server configurations only
|
||||
* ``server-cert.pem`` - mandatory; for server configurations only
|
||||
* ``server-key.pem`` - mandatory; for server configurations only
|
||||
* ``client-cert.pem`` - optional; for client configurations only
|
||||
* ``client-key.pem`` - optional; for client configurations only
|
||||
* ``dh-params.pem`` - optional; for server configurations only
|
||||
|
||||
Since QEMU 10.2.0, there is support for loading upto four additional
|
||||
identities:
|
||||
|
||||
* ``server-cert-[IDX].pem`` - optional; for server configurations only
|
||||
* ``server-key-[IDX].pem`` - optional; for server configurations only
|
||||
* ``client-cert-[IDX].pem`` - optional; for client configurations only
|
||||
* ``client-key-[IDX].pem`` - optional; for client configurations only
|
||||
|
||||
where ``-[IDX]`` is one of the digits 0-3. Loading will terminate at
|
||||
the first absent index. The index based certificate files may be used
|
||||
as a replacement for, or in addition to, the traditional non-index
|
||||
based certificate files. The traditional certificate files will be
|
||||
loaded first, if present, then the index based certificates. Where
|
||||
multiple certificates are compatible with a TLS session, the first
|
||||
loaded certificate will preferred. IOW file naming can influence
|
||||
which certificates are used for a session.
|
||||
|
||||
The use of multiple sets of certificates is intended to allow an
|
||||
incremental transition to certificates using different crytographic
|
||||
algorithms. This allows a newly deployed QEMU to introduce use of
|
||||
stronger cryptographic algorithms that will be preferred when talking
|
||||
to other newly deployed QEMU instances, while retaining compatbility
|
||||
with certificates issued to a historically deployed QEMU. This is
|
||||
notably useful to support live migration from an old QEMU deployed
|
||||
on older operating system releases, which may support fewer crypto
|
||||
algorithm choices than the current OS.
|
||||
|
||||
The certificate creation commands below will be illustrated using
|
||||
the traditional naming scheme, but their args can be substituted
|
||||
to use the indexed naming in the obvious manner.
|
||||
|
||||
.. _tls_005fgenerate_005fca:
|
||||
|
||||
@@ -251,11 +301,13 @@ When specifying the object, the ``dir`` parameters specifies which
|
||||
directory contains the credential files. This directory is expected to
|
||||
contain files with the names mentioned previously, ``ca-cert.pem``,
|
||||
``server-key.pem``, ``server-cert.pem``, ``client-key.pem`` and
|
||||
``client-cert.pem`` as appropriate. It is also possible to include a set
|
||||
of pre-generated Diffie-Hellman (DH) parameters in a file
|
||||
``dh-params.pem``, which can be created using the
|
||||
``certtool --generate-dh-params`` command. If omitted, QEMU will
|
||||
dynamically generate DH parameters when loading the credentials.
|
||||
``client-cert.pem`` as appropriate.
|
||||
|
||||
While it is possible to include a set of pre-generated Diffie-Hellman
|
||||
(DH) parameters in a file ``dh-params.pem``, this facility is now
|
||||
deprecated and will be removed in a future release. When omitted the
|
||||
DH parameters will be automatically negotiated in accordance with
|
||||
RFC7919.
|
||||
|
||||
The ``endpoint`` parameter indicates whether the credentials will be
|
||||
used for a network client or server, and determines which PEM files are
|
||||
@@ -293,6 +345,74 @@ example with VNC:
|
||||
|
||||
.. _tls_005fpsk:
|
||||
|
||||
TLS certificates for Post-Quantum Cryptography
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Given a new enough gnutls release, suitably integrated & configured with the
|
||||
operating system crypto policies, QEMU is able to support post-quantum
|
||||
crytography on TLS enabled services, either exclusively or in a hybrid mode.
|
||||
|
||||
In exclusive mode, only a single set of certificates need to be configured
|
||||
for QEMU, with PQC compliant algorithms. Such a QEMU configuration will only
|
||||
be able to interoperate with other services (including other QEMU's) that
|
||||
also have PQC enabled. This can result in compatibility concerns during the
|
||||
period of transition over to PQC compliant algorithms.
|
||||
|
||||
In hybrid mode, multiple sets of certificates need to be configured for QEMU,
|
||||
at least one set with traditional (non-PQC compliant) algorithms, and at least
|
||||
one other set with modern (PQC compliant) algorithms. At time of the TLS
|
||||
handshake, the GNUTLS algorithm priorities should ensure that PQC compliant
|
||||
algorithms are negotiated if both sides of the connection support PQC. If one
|
||||
side lacks PQC, the TLS handshake should fallback to the non-PQC algorithms.
|
||||
This can assist with interoperability during the transition to PQC, but has a
|
||||
potential weakness wrt downgrade attacks forcing use of non-PQC algorithms.
|
||||
Exclusive PQC mode should be preferred where both peers in the TLS connections
|
||||
are known to support PQC.
|
||||
|
||||
Key generation parameters
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To create certificates with PQC compliant algorithms, the ``--key-type``
|
||||
argument must be passed to ``certtool`` when creating private keys. No
|
||||
extra arguments are required for the other ``certtool`` commands, as
|
||||
their behaviour will be determined by the private key type.
|
||||
|
||||
The typical PQC compliant algorithms to use are ``ML-DSA-44``, ``ML-DSA-65``
|
||||
and ``ML-DSA-87``, with ``ML-DSA-65`` being a suitable default choice in
|
||||
the absence of explicit requirements.
|
||||
|
||||
Taking the example earlier, for creating a key for a client certificate,
|
||||
to use ``ML-DSA-65`` the command line would be modified to look like::
|
||||
|
||||
# certtool --generate-privkey --key-type=mldsa65 > client-hostNNN-key.pem
|
||||
|
||||
The equivalent modification applies to the creation of the private keys
|
||||
used for server certs, or root/intermediate CA certs.
|
||||
|
||||
For hybrid mode, the additional indexed certificate naming must be used.
|
||||
If multiple configured certificates are compatible with the mutually
|
||||
supported crypto algorithms between the client and server, then the
|
||||
first matching certificate will be used.
|
||||
|
||||
IOW, to ensure that PQC certificates are preferred, they must use a
|
||||
non-index based filename, or use an index that is smaller than any
|
||||
non-PQC certificates. ie, ``server-cert.pem`` for PQC and ``server-cert-0.pem``
|
||||
for non-PQC, or ``server-cert-0.pem`` for PQC and ``server-cert-1.pem`` for
|
||||
non-PQC.
|
||||
|
||||
Force disabling PQC via crypto priority
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In the OS configuration for system crypto algorithm priorities has
|
||||
enabled PQC, this can (optionally) be overriden in QEMU configuration
|
||||
disable use of PQC using the ``priority`` parameter to the ``tls-creds-x509``
|
||||
object::
|
||||
|
||||
NO_MLDSA="-SIGN-ML-DSA-65:-SIGN-ML-DSA-44:-SIGN-ML-DSA-87"
|
||||
NO_MLKEM="-GROUP-X25519-MLKEM768:-GROUP-SECP256R1-MLKEM768:-GROUP-SECP384R1-MLKEM1024"
|
||||
# qemu-nbd --object tls-creds-x509,id=tls0,endpoint=server,dir=....,priority=@SYSTEM:$NO_MLDSA:$NO_MLKEM
|
||||
|
||||
|
||||
TLS Pre-Shared Keys (PSK)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ int qcrypto_hash_bytesv(QCryptoHashAlgo alg,
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int qcrypto_hash_bytes(QCryptoHashAlgo alg,
|
||||
const char *buf,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
uint8_t **result,
|
||||
size_t *resultlen,
|
||||
@@ -180,7 +180,7 @@ int qcrypto_hash_updatev(QCryptoHash *hash,
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int qcrypto_hash_update(QCryptoHash *hash,
|
||||
const char *buf,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
Error **errp);
|
||||
|
||||
@@ -289,7 +289,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoHash, qcrypto_hash_free)
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int qcrypto_hash_digest(QCryptoHashAlgo alg,
|
||||
const char *buf,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
char **digest,
|
||||
Error **errp);
|
||||
@@ -335,7 +335,7 @@ int qcrypto_hash_base64v(QCryptoHashAlgo alg,
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int qcrypto_hash_base64(QCryptoHashAlgo alg,
|
||||
const char *buf,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
char **base64,
|
||||
Error **errp);
|
||||
|
||||
@@ -139,7 +139,7 @@ int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
|
||||
* 0 on success, -1 on error
|
||||
*/
|
||||
int qcrypto_hmac_bytes(QCryptoHmac *hmac,
|
||||
const char *buf,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
uint8_t **result,
|
||||
size_t *resultlen,
|
||||
@@ -187,7 +187,7 @@ int qcrypto_hmac_digestv(QCryptoHmac *hmac,
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int qcrypto_hmac_digest(QCryptoHmac *hmac,
|
||||
const char *buf,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
char **digest,
|
||||
Error **errp);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user