encryption: Add <cipher> and <ivgen> to encryption

For a luks device, allow the configuration of a specific cipher to be
used for encrypting the volume.

Signed-off-by: John Ferlan <jferlan@redhat.com>
This commit is contained in:
John Ferlan
2016-07-01 15:46:57 -04:00
parent 9bbf0d7e64
commit 2552fec248
11 changed files with 376 additions and 6 deletions
+11
View File
@@ -7802,6 +7802,17 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
def->startupPolicy = val;
}
if (encryption) {
if (encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS &&
encryption->encinfo.cipher_name) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("supplying the <cipher> for a domain is "
"unnecessary"));
goto error;
}
}
def->dst = target;
target = NULL;
def->src->auth = authdef;
+136
View File
@@ -35,6 +35,7 @@
#include "viruuid.h"
#include "virfile.h"
#include "virsecret.h"
#include "virstring.h"
#define VIR_FROM_THIS VIR_FROM_STORAGE
@@ -45,6 +46,17 @@ VIR_ENUM_IMPL(virStorageEncryptionFormat,
VIR_STORAGE_ENCRYPTION_FORMAT_LAST,
"default", "qcow", "luks")
static void
virStorageEncryptionInfoDefFree(virStorageEncryptionInfoDefPtr def)
{
VIR_FREE(def->cipher_name);
VIR_FREE(def->cipher_mode);
VIR_FREE(def->cipher_hash);
VIR_FREE(def->ivgen_name);
VIR_FREE(def->ivgen_hash);
}
static void
virStorageEncryptionSecretFree(virStorageEncryptionSecretPtr secret)
{
@@ -63,6 +75,7 @@ virStorageEncryptionFree(virStorageEncryptionPtr enc)
for (i = 0; i < enc->nsecrets; i++)
virStorageEncryptionSecretFree(enc->secrets[i]);
virStorageEncryptionInfoDefFree(&enc->encinfo);
VIR_FREE(enc->secrets);
VIR_FREE(enc);
}
@@ -80,6 +93,23 @@ virStorageEncryptionSecretCopy(const virStorageEncryptionSecret *src)
return ret;
}
static int
virStorageEncryptionInfoDefCopy(const virStorageEncryptionInfoDef *src,
virStorageEncryptionInfoDefPtr dst)
{
dst->cipher_size = src->cipher_size;
if (VIR_STRDUP(dst->cipher_name, src->cipher_name) < 0 ||
VIR_STRDUP(dst->cipher_mode, src->cipher_mode) < 0 ||
VIR_STRDUP(dst->cipher_hash, src->cipher_hash) < 0 ||
VIR_STRDUP(dst->ivgen_name, src->ivgen_name) < 0 ||
VIR_STRDUP(dst->ivgen_hash, src->ivgen_hash) < 0)
return -1;
return 0;
}
virStorageEncryptionPtr
virStorageEncryptionCopy(const virStorageEncryption *src)
{
@@ -100,6 +130,9 @@ virStorageEncryptionCopy(const virStorageEncryption *src)
goto error;
}
if (virStorageEncryptionInfoDefCopy(&src->encinfo, &ret->encinfo) < 0)
goto error;
return ret;
error:
@@ -153,6 +186,61 @@ virStorageEncryptionSecretParse(xmlXPathContextPtr ctxt,
return NULL;
}
static int
virStorageEncryptionInfoParseCipher(xmlNodePtr info_node,
virStorageEncryptionInfoDefPtr info)
{
int ret = -1;
char *size_str = NULL;
if (!(info->cipher_name = virXMLPropString(info_node, "name"))) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("cipher info missing 'name' attribute"));
goto cleanup;
}
if ((size_str = virXMLPropString(info_node, "size")) &&
virStrToLong_uip(size_str, NULL, 10, &info->cipher_size) < 0) {
virReportError(VIR_ERR_XML_ERROR,
_("cannot parse cipher size: '%s'"),
size_str);
goto cleanup;
}
if (!size_str) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("cipher info missing 'size' attribute"));
goto cleanup;
}
info->cipher_mode = virXMLPropString(info_node, "mode");
info->cipher_hash = virXMLPropString(info_node, "hash");
ret = 0;
cleanup:
VIR_FREE(size_str);
return ret;
}
static int
virStorageEncryptionInfoParseIvgen(xmlNodePtr info_node,
virStorageEncryptionInfoDefPtr info)
{
if (!(info->ivgen_name = virXMLPropString(info_node, "name"))) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("missing ivgen info name string"));
return -1;
}
info->ivgen_hash = virXMLPropString(info_node, "hash");
return 0;
}
static virStorageEncryptionPtr
virStorageEncryptionParseXML(xmlXPathContextPtr ctxt)
{
@@ -196,6 +284,28 @@ virStorageEncryptionParseXML(xmlXPathContextPtr ctxt)
VIR_FREE(nodes);
}
if (ret->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) {
xmlNodePtr tmpnode;
if ((tmpnode = virXPathNode("./cipher[1]", ctxt))) {
if (virStorageEncryptionInfoParseCipher(tmpnode, &ret->encinfo) < 0)
goto cleanup;
}
if ((tmpnode = virXPathNode("./ivgen[1]", ctxt))) {
/* If no cipher node, then fail */
if (!ret->encinfo.cipher_name) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("ivgen element found, but cipher is missing"));
goto cleanup;
}
if (virStorageEncryptionInfoParseIvgen(tmpnode, &ret->encinfo) < 0)
goto cleanup;
}
}
return ret;
cleanup:
@@ -250,6 +360,28 @@ virStorageEncryptionSecretFormat(virBufferPtr buf,
return 0;
}
static void
virStorageEncryptionInfoDefFormat(virBufferPtr buf,
const virStorageEncryptionInfoDef *enc)
{
virBufferEscapeString(buf, "<cipher name='%s'", enc->cipher_name);
virBufferAsprintf(buf, " size='%u'", enc->cipher_size);
if (enc->cipher_mode)
virBufferEscapeString(buf, " mode='%s'", enc->cipher_mode);
if (enc->cipher_hash)
virBufferEscapeString(buf, " hash='%s'", enc->cipher_hash);
virBufferAddLit(buf, "/>\n");
if (enc->ivgen_name) {
virBufferEscapeString(buf, "<ivgen name='%s'", enc->ivgen_name);
if (enc->ivgen_hash)
virBufferEscapeString(buf, " hash='%s'", enc->ivgen_hash);
virBufferAddLit(buf, "/>\n");
}
}
int
virStorageEncryptionFormat(virBufferPtr buf,
virStorageEncryptionPtr enc)
@@ -270,6 +402,10 @@ virStorageEncryptionFormat(virBufferPtr buf,
return -1;
}
if (enc->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS &&
enc->encinfo.cipher_name)
virStorageEncryptionInfoDefFormat(buf, &enc->encinfo);
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</encryption>\n");
+14
View File
@@ -44,6 +44,18 @@ struct _virStorageEncryptionSecret {
virSecretLookupTypeDef seclookupdef;
};
/* It's possible to dictate the cipher and if necessary iv */
typedef struct _virStorageEncryptionInfoDef virStorageEncryptionInfoDef;
typedef virStorageEncryptionInfoDef *virStorageEncryptionInfoDefPtr;
struct _virStorageEncryptionInfoDef {
unsigned int cipher_size;
char *cipher_name;
char *cipher_mode;
char *cipher_hash;
char *ivgen_name;
char *ivgen_hash;
};
typedef enum {
/* "default" is only valid for volume creation */
VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT = 0,
@@ -61,6 +73,8 @@ struct _virStorageEncryption {
size_t nsecrets;
virStorageEncryptionSecretPtr *secrets;
virStorageEncryptionInfoDef encinfo;
};
virStorageEncryptionPtr virStorageEncryptionCopy(const virStorageEncryption *src)