crypto: add support for loading encrypted x509 keys
Make use of the QCryptoSecret object to support loading of encrypted x509 keys. The optional 'passwordid' parameter to the tls-creds-x509 object type, provides the ID of a secret object instance that holds the decryption password for the PEM file. # printf "123456" > mypasswd.txt # $QEMU \ -object secret,id=sec0,filename=mypasswd.txt \ -object tls-creds-x509,passwordid=sec0,id=creds0,\ dir=/home/berrange/.pki/qemu,endpoint=server \ -vnc :1,tls-creds=creds0 This requires QEMU to be linked to GNUTLS >= 3.1.11. If GNUTLS is too old an error will be reported if an attempt is made to pass a decryption password. Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
parent
ac1d887849
commit
1d7b5b4afd
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "crypto/tlscredsx509.h"
|
#include "crypto/tlscredsx509.h"
|
||||||
#include "crypto/tlscredspriv.h"
|
#include "crypto/tlscredspriv.h"
|
||||||
|
#include "crypto/secret.h"
|
||||||
#include "qom/object_interfaces.h"
|
#include "qom/object_interfaces.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
@ -607,9 +608,30 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cert != NULL && key != NULL) {
|
if (cert != NULL && key != NULL) {
|
||||||
|
#if GNUTLS_VERSION_NUMBER >= 0x030111
|
||||||
|
char *password = NULL;
|
||||||
|
if (creds->passwordid) {
|
||||||
|
password = qcrypto_secret_lookup_as_utf8(creds->passwordid,
|
||||||
|
errp);
|
||||||
|
if (!password) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = gnutls_certificate_set_x509_key_file2(creds->data,
|
||||||
|
cert, key,
|
||||||
|
GNUTLS_X509_FMT_PEM,
|
||||||
|
password,
|
||||||
|
0);
|
||||||
|
g_free(password);
|
||||||
|
#else /* GNUTLS_VERSION_NUMBER < 0x030111 */
|
||||||
|
if (creds->passwordid) {
|
||||||
|
error_setg(errp, "PKCS8 decryption requires GNUTLS >= 3.1.11");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
ret = gnutls_certificate_set_x509_key_file(creds->data,
|
ret = gnutls_certificate_set_x509_key_file(creds->data,
|
||||||
cert, key,
|
cert, key,
|
||||||
GNUTLS_X509_FMT_PEM);
|
GNUTLS_X509_FMT_PEM);
|
||||||
|
#endif /* GNUTLS_VERSION_NUMBER < 0x030111 */
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_setg(errp, "Cannot load certificate '%s' & key '%s': %s",
|
error_setg(errp, "Cannot load certificate '%s' & key '%s': %s",
|
||||||
cert, key, gnutls_strerror(ret));
|
cert, key, gnutls_strerror(ret));
|
||||||
@ -737,6 +759,27 @@ qcrypto_tls_creds_x509_prop_set_sanity(Object *obj,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
qcrypto_tls_creds_x509_prop_set_passwordid(Object *obj,
|
||||||
|
const char *value,
|
||||||
|
Error **errp G_GNUC_UNUSED)
|
||||||
|
{
|
||||||
|
QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
|
||||||
|
|
||||||
|
creds->passwordid = g_strdup(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
qcrypto_tls_creds_x509_prop_get_passwordid(Object *obj,
|
||||||
|
Error **errp G_GNUC_UNUSED)
|
||||||
|
{
|
||||||
|
QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
|
||||||
|
|
||||||
|
return g_strdup(creds->passwordid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
qcrypto_tls_creds_x509_prop_get_sanity(Object *obj,
|
qcrypto_tls_creds_x509_prop_get_sanity(Object *obj,
|
||||||
Error **errp G_GNUC_UNUSED)
|
Error **errp G_GNUC_UNUSED)
|
||||||
@ -769,6 +812,10 @@ qcrypto_tls_creds_x509_init(Object *obj)
|
|||||||
qcrypto_tls_creds_x509_prop_get_sanity,
|
qcrypto_tls_creds_x509_prop_get_sanity,
|
||||||
qcrypto_tls_creds_x509_prop_set_sanity,
|
qcrypto_tls_creds_x509_prop_set_sanity,
|
||||||
NULL);
|
NULL);
|
||||||
|
object_property_add_str(obj, "passwordid",
|
||||||
|
qcrypto_tls_creds_x509_prop_get_passwordid,
|
||||||
|
qcrypto_tls_creds_x509_prop_set_passwordid,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -777,6 +824,7 @@ qcrypto_tls_creds_x509_finalize(Object *obj)
|
|||||||
{
|
{
|
||||||
QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
|
QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
|
||||||
|
|
||||||
|
g_free(creds->passwordid);
|
||||||
qcrypto_tls_creds_x509_unload(creds);
|
qcrypto_tls_creds_x509_unload(creds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +101,7 @@ struct QCryptoTLSCredsX509 {
|
|||||||
gnutls_certificate_credentials_t data;
|
gnutls_certificate_credentials_t data;
|
||||||
#endif
|
#endif
|
||||||
bool sanityCheck;
|
bool sanityCheck;
|
||||||
|
char *passwordid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -3627,7 +3627,7 @@ expensive operation that consumes random pool entropy, so it is
|
|||||||
recommended that a persistent set of parameters be generated
|
recommended that a persistent set of parameters be generated
|
||||||
upfront and saved.
|
upfront and saved.
|
||||||
|
|
||||||
@item -object tls-creds-x509,id=@var{id},endpoint=@var{endpoint},dir=@var{/path/to/cred/dir},verify-peer=@var{on|off}
|
@item -object tls-creds-x509,id=@var{id},endpoint=@var{endpoint},dir=@var{/path/to/cred/dir},verify-peer=@var{on|off},passwordid=@var{id}
|
||||||
|
|
||||||
Creates a TLS anonymous credentials object, which can be used to provide
|
Creates a TLS anonymous credentials object, which can be used to provide
|
||||||
TLS support on network backends. The @option{id} parameter is a unique
|
TLS support on network backends. The @option{id} parameter is a unique
|
||||||
@ -3654,6 +3654,12 @@ in PEM format, in filenames @var{ca-cert.pem}, @var{ca-crl.pem} (optional),
|
|||||||
@var{server-cert.pem} (only servers), @var{server-key.pem} (only servers),
|
@var{server-cert.pem} (only servers), @var{server-key.pem} (only servers),
|
||||||
@var{client-cert.pem} (only clients), and @var{client-key.pem} (only clients).
|
@var{client-cert.pem} (only clients), and @var{client-key.pem} (only clients).
|
||||||
|
|
||||||
|
For the @var{server-key.pem} and @var{client-key.pem} files which
|
||||||
|
contain sensitive private keys, it is possible to use an encrypted
|
||||||
|
version by providing the @var{passwordid} parameter. This provides
|
||||||
|
the ID of a previously created @code{secret} object containing the
|
||||||
|
password for decryption.
|
||||||
|
|
||||||
@item -object filter-buffer,id=@var{id},netdev=@var{netdevid},interval=@var{t}[,queue=@var{all|rx|tx}]
|
@item -object filter-buffer,id=@var{id},netdev=@var{netdevid},interval=@var{t}[,queue=@var{all|rx|tx}]
|
||||||
|
|
||||||
Interval @var{t} can't be 0, this filter batches the packet delivery: all
|
Interval @var{t} can't be 0, this filter batches the packet delivery: all
|
||||||
|
Loading…
Reference in New Issue
Block a user