提交 adb99a05 编写于 作者: M Michal Privoznik

storage: Support different wiping algorithms

Currently, we support only filling a volume with zeroes on wiping.
However, it is not enough as data might still be readable by
experienced and equipped attacker. Many technical papers have been
written, therefore we should support other wiping algorithms.
上级 7fb22418
...@@ -2500,8 +2500,31 @@ AM_CONDITIONAL([HAVE_LIBNL], [test "$have_libnl" = "yes"]) ...@@ -2500,8 +2500,31 @@ AM_CONDITIONAL([HAVE_LIBNL], [test "$have_libnl" = "yes"])
AC_SUBST([LIBNL_CFLAGS]) AC_SUBST([LIBNL_CFLAGS])
AC_SUBST([LIBNL_LIBS]) AC_SUBST([LIBNL_LIBS])
dnl scrub program for different volume wiping algorithms
AC_ARG_WITH([scrub],
AC_HELP_STRING([--with-scrub], [enable different volume wiping algorithms
@<:@default=check@:>@]),
[with_macvtap=${withval}],
[with_scrub=check])
if test "$with_scrub" != "no"; then
AC_PATH_PROG([SCRUB], [scrub])
if test -z "$SCRUB" ; then
if test "$with_scrub" = "check"; then
with_scrub=no
else
AC_MSG_ERROR([You must install the 'scrub' binary to enable
different volume wiping algorithms])
fi
else
with_scrub=yes
fi
if test "$with_scrub" = "yes"; then
AC_DEFINE_UNQUOTED([SCRUB], ["$SCRUB"],
[Location of the scrub program])
fi
fi
# Only COPYING.LIB is under version control, yet COPYING # Only COPYING.LIB is under version control, yet COPYING
# is included as part of the distribution tarball. # is included as part of the distribution tarball.
......
...@@ -2207,6 +2207,35 @@ typedef enum { ...@@ -2207,6 +2207,35 @@ typedef enum {
VIR_STORAGE_VOL_DELETE_ZEROED = 1 << 0, /* Clear all data to zeros (slow) */ VIR_STORAGE_VOL_DELETE_ZEROED = 1 << 0, /* Clear all data to zeros (slow) */
} virStorageVolDeleteFlags; } virStorageVolDeleteFlags;
typedef enum {
VIR_STORAGE_VOL_WIPE_ALG_ZERO = 0, /* 1-pass, all zeroes */
VIR_STORAGE_VOL_WIPE_ALG_NNSA = 1, /* 4-pass NNSA Policy Letter
NAP-14.1-C (XVI-8) */
VIR_STORAGE_VOL_WIPE_ALG_DOD = 2, /* 4-pass DoD 5220.22-M section
8-306 procedure */
VIR_STORAGE_VOL_WIPE_ALG_BSI = 3, /* 9-pass method recommended by the
German Center of Security in
Information Technologies */
VIR_STORAGE_VOL_WIPE_ALG_GUTMANN = 4, /* The canonical 35-pass sequence */
VIR_STORAGE_VOL_WIPE_ALG_SCHNEIER = 5, /* 7-pass method described by
Bruce Schneier in "Applied
Cryptography" (1996) */
VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7 = 6, /* 7-pass random */
VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33 = 7, /* 33-pass random */
VIR_STORAGE_VOL_WIPE_ALG_RANDOM = 8, /* 1-pass random */
#ifdef VIR_ENUM_SENTINELS
/*
* NB: this enum value will increase over time as new algorithms are
* added to the libvirt API. It reflects the last algorithm supported
* by this version of the libvirt API.
*/
VIR_STORAGE_VOL_WIPE_ALG_LAST
#endif
} virStorageVolWipeAlgorithm;
typedef struct _virStorageVolInfo virStorageVolInfo; typedef struct _virStorageVolInfo virStorageVolInfo;
struct _virStorageVolInfo { struct _virStorageVolInfo {
...@@ -2344,6 +2373,9 @@ int virStorageVolDelete (virStorageVolPtr vol, ...@@ -2344,6 +2373,9 @@ int virStorageVolDelete (virStorageVolPtr vol,
unsigned int flags); unsigned int flags);
int virStorageVolWipe (virStorageVolPtr vol, int virStorageVolWipe (virStorageVolPtr vol,
unsigned int flags); unsigned int flags);
int virStorageVolWipePattern (virStorageVolPtr vol,
unsigned int algorithm,
unsigned int flags);
int virStorageVolRef (virStorageVolPtr vol); int virStorageVolRef (virStorageVolPtr vol);
int virStorageVolFree (virStorageVolPtr vol); int virStorageVolFree (virStorageVolPtr vol);
......
...@@ -1230,6 +1230,10 @@ typedef int ...@@ -1230,6 +1230,10 @@ typedef int
typedef int typedef int
(*virDrvStorageVolWipe) (virStorageVolPtr vol, (*virDrvStorageVolWipe) (virStorageVolPtr vol,
unsigned int flags); unsigned int flags);
typedef int
(*virDrvStorageVolWipePattern) (virStorageVolPtr vol,
unsigned int algorithm,
unsigned int flags);
typedef int typedef int
(*virDrvStorageVolGetInfo) (virStorageVolPtr vol, (*virDrvStorageVolGetInfo) (virStorageVolPtr vol,
...@@ -1315,6 +1319,7 @@ struct _virStorageDriver { ...@@ -1315,6 +1319,7 @@ struct _virStorageDriver {
virDrvStorageVolUpload volUpload; virDrvStorageVolUpload volUpload;
virDrvStorageVolDelete volDelete; virDrvStorageVolDelete volDelete;
virDrvStorageVolWipe volWipe; virDrvStorageVolWipe volWipe;
virDrvStorageVolWipePattern volWipePattern;
virDrvStorageVolGetInfo volGetInfo; virDrvStorageVolGetInfo volGetInfo;
virDrvStorageVolGetXMLDesc volGetXMLDesc; virDrvStorageVolGetXMLDesc volGetXMLDesc;
virDrvStorageVolGetPath volGetPath; virDrvStorageVolGetPath volGetPath;
......
...@@ -12681,6 +12681,55 @@ error: ...@@ -12681,6 +12681,55 @@ error:
} }
/**
* virStorageVolWipePattern:
* @vol: pointer to storage volume
* @algorithm: one of virStorageVolWipeAlgorithm
* @flags: future flags, use 0 for now
*
* Similar to virStorageVolWipe, but one can choose
* between different wiping algorithms.
*
* Returns 0 on success, or -1 on error.
*/
int
virStorageVolWipePattern(virStorageVolPtr vol,
unsigned int algorithm,
unsigned int flags)
{
virConnectPtr conn;
VIR_DEBUG("vol=%p, algorithm=%u, flags=%x", vol, algorithm, flags);
virResetLastError();
if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) {
virLibStorageVolError(VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
virDispatchError(NULL);
return -1;
}
conn = vol->conn;
if (conn->flags & VIR_CONNECT_RO) {
virLibStorageVolError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
goto error;
}
if (conn->storageDriver && conn->storageDriver->volWipePattern) {
int ret;
ret = conn->storageDriver->volWipePattern(vol, algorithm, flags);
if (ret < 0) {
goto error;
}
return ret;
}
virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
error:
virDispatchError(vol->conn);
return -1;
}
/** /**
* virStorageVolFree: * virStorageVolFree:
* @vol: pointer to storage volume * @vol: pointer to storage volume
......
...@@ -519,5 +519,7 @@ LIBVIRT_0.9.9 { ...@@ -519,5 +519,7 @@ LIBVIRT_0.9.9 {
LIBVIRT_0.9.10 { LIBVIRT_0.9.10 {
global: global:
virDomainShutdownFlags; virDomainShutdownFlags;
virStorageVolWipePattern;
} LIBVIRT_0.9.9; } LIBVIRT_0.9.9;
# .... define new API here using predicted next version number .... # .... define new API here using predicted next version number ....
...@@ -4833,6 +4833,7 @@ static virStorageDriver storage_driver = { ...@@ -4833,6 +4833,7 @@ static virStorageDriver storage_driver = {
.volUpload = remoteStorageVolUpload, /* 0.9.0 */ .volUpload = remoteStorageVolUpload, /* 0.9.0 */
.volDelete = remoteStorageVolDelete, /* 0.4.1 */ .volDelete = remoteStorageVolDelete, /* 0.4.1 */
.volWipe = remoteStorageVolWipe, /* 0.8.0 */ .volWipe = remoteStorageVolWipe, /* 0.8.0 */
.volWipePattern = remoteStorageVolWipePattern, /* 0.9.10 */
.volGetInfo = remoteStorageVolGetInfo, /* 0.4.1 */ .volGetInfo = remoteStorageVolGetInfo, /* 0.4.1 */
.volGetXMLDesc = remoteStorageVolGetXMLDesc, /* 0.4.1 */ .volGetXMLDesc = remoteStorageVolGetXMLDesc, /* 0.4.1 */
.volGetPath = remoteStorageVolGetPath, /* 0.4.1 */ .volGetPath = remoteStorageVolGetPath, /* 0.4.1 */
......
...@@ -1643,6 +1643,12 @@ struct remote_storage_vol_wipe_args { ...@@ -1643,6 +1643,12 @@ struct remote_storage_vol_wipe_args {
unsigned int flags; unsigned int flags;
}; };
struct remote_storage_vol_wipe_pattern_args {
remote_nonnull_storage_vol vol;
unsigned int algorithm;
unsigned int flags;
};
struct remote_storage_vol_get_xml_desc_args { struct remote_storage_vol_get_xml_desc_args {
remote_nonnull_storage_vol vol; remote_nonnull_storage_vol vol;
unsigned int flags; unsigned int flags;
...@@ -2660,7 +2666,8 @@ enum remote_procedure { ...@@ -2660,7 +2666,8 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_GET_NUMA_PARAMETERS = 255, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_GET_NUMA_PARAMETERS = 255, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_SET_INTERFACE_PARAMETERS = 256, /* autogen autogen */ REMOTE_PROC_DOMAIN_SET_INTERFACE_PARAMETERS = 256, /* autogen autogen */
REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_SHUTDOWN_FLAGS = 258 /* autogen autogen */ REMOTE_PROC_DOMAIN_SHUTDOWN_FLAGS = 258, /* autogen autogen */
REMOTE_PROC_STORAGE_VOL_WIPE_PATTERN = 259 /* autogen autogen */
/* /*
* Notice how the entries are grouped in sets of 10 ? * Notice how the entries are grouped in sets of 10 ?
......
...@@ -1234,6 +1234,11 @@ struct remote_storage_vol_wipe_args { ...@@ -1234,6 +1234,11 @@ struct remote_storage_vol_wipe_args {
remote_nonnull_storage_vol vol; remote_nonnull_storage_vol vol;
u_int flags; u_int flags;
}; };
struct remote_storage_vol_wipe_pattern_args {
remote_nonnull_storage_vol vol;
u_int algorithm;
u_int flags;
};
struct remote_storage_vol_get_xml_desc_args { struct remote_storage_vol_get_xml_desc_args {
remote_nonnull_storage_vol vol; remote_nonnull_storage_vol vol;
u_int flags; u_int flags;
...@@ -2095,4 +2100,5 @@ enum remote_procedure { ...@@ -2095,4 +2100,5 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_SET_INTERFACE_PARAMETERS = 256, REMOTE_PROC_DOMAIN_SET_INTERFACE_PARAMETERS = 256,
REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257, REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257,
REMOTE_PROC_DOMAIN_SHUTDOWN_FLAGS = 258, REMOTE_PROC_DOMAIN_SHUTDOWN_FLAGS = 258,
REMOTE_PROC_STORAGE_VOL_WIPE_PATTERN = 259,
}; };
...@@ -1801,14 +1801,17 @@ out: ...@@ -1801,14 +1801,17 @@ out:
static int static int
storageVolumeWipeInternal(virStorageVolDefPtr def) storageVolumeWipeInternal(virStorageVolDefPtr def,
unsigned int algorithm)
{ {
int ret = -1, fd = -1; int ret = -1, fd = -1;
struct stat st; struct stat st;
char *writebuf = NULL; char *writebuf = NULL;
size_t bytes_wiped = 0; size_t bytes_wiped = 0;
virCommandPtr cmd = NULL;
VIR_DEBUG("Wiping volume with path '%s'", def->target.path); VIR_DEBUG("Wiping volume with path '%s' and algorithm %u",
def->target.path, algorithm);
fd = open(def->target.path, O_RDWR); fd = open(def->target.path, O_RDWR);
if (fd == -1) { if (fd == -1) {
...@@ -1825,36 +1828,83 @@ storageVolumeWipeInternal(virStorageVolDefPtr def) ...@@ -1825,36 +1828,83 @@ storageVolumeWipeInternal(virStorageVolDefPtr def)
goto out; goto out;
} }
if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) { if (algorithm != VIR_STORAGE_VOL_WIPE_ALG_ZERO) {
ret = storageVolumeZeroSparseFile(def, st.st_size, fd); const char *alg_char ATTRIBUTE_UNUSED = NULL;
} else { switch (algorithm) {
#ifdef SCRUB
case VIR_STORAGE_VOL_WIPE_ALG_NNSA:
alg_char = "nnsa";
break;
case VIR_STORAGE_VOL_WIPE_ALG_DOD:
alg_char = "dod";
break;
case VIR_STORAGE_VOL_WIPE_ALG_BSI:
alg_char = "bsi";
break;
case VIR_STORAGE_VOL_WIPE_ALG_GUTMANN:
alg_char = "gutmann";
break;
case VIR_STORAGE_VOL_WIPE_ALG_SCHNEIER:
alg_char = "shneier";
break;
case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7:
alg_char = "pfitzner7";
break;
case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33:
alg_char = " pfitzner33";
break;
case VIR_STORAGE_VOL_WIPE_ALG_RANDOM:
alg_char = "random";
break;
#endif
default:
virStorageReportError(VIR_ERR_INVALID_ARG,
_("unsupported algorithm %d"),
algorithm);
}
#ifdef SCRUB
cmd = virCommandNew(SCRUB);
virCommandAddArgList(cmd, "-f", "-p", alg_char,
def->target.path, NULL);
if (VIR_ALLOC_N(writebuf, st.st_blksize) != 0) { if (virCommandRun(cmd, NULL) < 0)
virReportOOMError();
goto out; goto out;
}
ret = storageWipeExtent(def, ret = 0;
fd, #endif
0, goto out;
def->allocation, } else {
writebuf, if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
st.st_blksize, ret = storageVolumeZeroSparseFile(def, st.st_size, fd);
&bytes_wiped); } else {
if (VIR_ALLOC_N(writebuf, st.st_blksize) != 0) {
virReportOOMError();
goto out;
}
ret = storageWipeExtent(def,
fd,
0,
def->allocation,
writebuf,
st.st_blksize,
&bytes_wiped);
}
} }
out: out:
virCommandFree(cmd);
VIR_FREE(writebuf); VIR_FREE(writebuf);
VIR_FORCE_CLOSE(fd); VIR_FORCE_CLOSE(fd);
return ret; return ret;
} }
static int static int
storageVolumeWipe(virStorageVolPtr obj, storageVolumeWipePattern(virStorageVolPtr obj,
unsigned int flags) unsigned int algorithm,
unsigned int flags)
{ {
virStorageDriverStatePtr driver = obj->conn->storagePrivateData; virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
virStoragePoolObjPtr pool = NULL; virStoragePoolObjPtr pool = NULL;
...@@ -1863,6 +1913,13 @@ storageVolumeWipe(virStorageVolPtr obj, ...@@ -1863,6 +1913,13 @@ storageVolumeWipe(virStorageVolPtr obj,
virCheckFlags(0, -1); virCheckFlags(0, -1);
if (algorithm >= VIR_STORAGE_VOL_WIPE_ALG_LAST) {
virStorageReportError(VIR_ERR_INVALID_ARG,
_("wiping algorithm %d not supported"),
algorithm);
return -1;
}
storageDriverLock(driver); storageDriverLock(driver);
pool = virStoragePoolObjFindByName(&driver->pools, obj->pool); pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
storageDriverUnlock(driver); storageDriverUnlock(driver);
...@@ -1895,7 +1952,7 @@ storageVolumeWipe(virStorageVolPtr obj, ...@@ -1895,7 +1952,7 @@ storageVolumeWipe(virStorageVolPtr obj,
goto out; goto out;
} }
if (storageVolumeWipeInternal(vol) == -1) { if (storageVolumeWipeInternal(vol, algorithm) == -1) {
goto out; goto out;
} }
...@@ -1910,6 +1967,13 @@ out: ...@@ -1910,6 +1967,13 @@ out:
} }
static int
storageVolumeWipe(virStorageVolPtr obj,
unsigned int flags)
{
return storageVolumeWipePattern(obj, VIR_STORAGE_VOL_WIPE_ALG_ZERO, flags);
}
static int static int
storageVolumeDelete(virStorageVolPtr obj, storageVolumeDelete(virStorageVolPtr obj,
unsigned int flags) { unsigned int flags) {
...@@ -2175,6 +2239,7 @@ static virStorageDriver storageDriver = { ...@@ -2175,6 +2239,7 @@ static virStorageDriver storageDriver = {
.volUpload = storageVolumeUpload, /* 0.9.0 */ .volUpload = storageVolumeUpload, /* 0.9.0 */
.volDelete = storageVolumeDelete, /* 0.4.0 */ .volDelete = storageVolumeDelete, /* 0.4.0 */
.volWipe = storageVolumeWipe, /* 0.8.0 */ .volWipe = storageVolumeWipe, /* 0.8.0 */
.volWipePattern = storageVolumeWipePattern, /* 0.9.10 */
.volGetInfo = storageVolumeGetInfo, /* 0.4.0 */ .volGetInfo = storageVolumeGetInfo, /* 0.4.0 */
.volGetXMLDesc = storageVolumeGetXMLDesc, /* 0.4.0 */ .volGetXMLDesc = storageVolumeGetXMLDesc, /* 0.4.0 */
.volGetPath = storageVolumeGetPath, /* 0.4.0 */ .volGetPath = storageVolumeGetPath, /* 0.4.0 */
......
...@@ -11160,15 +11160,24 @@ static const vshCmdInfo info_vol_wipe[] = { ...@@ -11160,15 +11160,24 @@ static const vshCmdInfo info_vol_wipe[] = {
static const vshCmdOptDef opts_vol_wipe[] = { static const vshCmdOptDef opts_vol_wipe[] = {
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")}, {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
{"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
{"algorithm", VSH_OT_STRING, 0, N_("perform selected wiping algorithm")},
{NULL, 0, 0, NULL} {NULL, 0, 0, NULL}
}; };
VIR_ENUM_DECL(virStorageVolWipeAlgorithm)
VIR_ENUM_IMPL(virStorageVolWipeAlgorithm, VIR_STORAGE_VOL_WIPE_ALG_LAST,
"zero", "nnsa", "dod", "bsi", "gutmann", "schneier",
"pfitzner7", "pfitzner33", "random");
static bool static bool
cmdVolWipe(vshControl *ctl, const vshCmd *cmd) cmdVolWipe(vshControl *ctl, const vshCmd *cmd)
{ {
virStorageVolPtr vol; virStorageVolPtr vol;
bool ret = true; bool ret = false;
const char *name; const char *name;
const char *algorithm_str = NULL;
int algorithm = VIR_STORAGE_VOL_WIPE_ALG_ZERO;
int funcRet;
if (!vshConnectionUsability(ctl, ctl->conn)) if (!vshConnectionUsability(ctl, ctl->conn))
return false; return false;
...@@ -11177,13 +11186,31 @@ cmdVolWipe(vshControl *ctl, const vshCmd *cmd) ...@@ -11177,13 +11186,31 @@ cmdVolWipe(vshControl *ctl, const vshCmd *cmd)
return false; return false;
} }
if (virStorageVolWipe(vol, 0) == 0) { if (vshCommandOptString(cmd, "algorithm", &algorithm_str) < 0) {
vshPrint(ctl, _("Vol %s wiped\n"), name); vshError(ctl, "%s", _("missing argument"));
} else { goto out;
}
if (algorithm_str &&
(algorithm = virStorageVolWipeAlgorithmTypeFromString(algorithm_str)) < 0) {
vshError(ctl, _("Unsupported algorithm '%s'"), algorithm_str);
goto out;
}
if ((funcRet = virStorageVolWipePattern(vol, algorithm, 0)) < 0) {
if (last_error->code == VIR_ERR_NO_SUPPORT &&
algorithm == VIR_STORAGE_VOL_WIPE_ALG_ZERO)
funcRet = virStorageVolWipe(vol, 0);
}
if (funcRet < 0) {
vshError(ctl, _("Failed to wipe vol %s"), name); vshError(ctl, _("Failed to wipe vol %s"), name);
ret = false; goto out;
} }
vshPrint(ctl, _("Vol %s wiped\n"), name);
ret = true;
out:
virStorageVolFree(vol); virStorageVolFree(vol);
return ret; return ret;
} }
......
...@@ -1934,12 +1934,36 @@ I<vol-name-or-key-or-path> is the name or key or path of the volume to wipe. ...@@ -1934,12 +1934,36 @@ I<vol-name-or-key-or-path> is the name or key or path of the volume to wipe.
I<--offset> is the position in the storage volume at which to start reading I<--offset> is the position in the storage volume at which to start reading
the data. I<--length> is an upper bound of the amount of data to be downloaded. the data. I<--length> is an upper bound of the amount of data to be downloaded.
=item B<vol-wipe> [I<--pool> I<pool-or-uuid>] I<vol-name-or-key-or-path> =item B<vol-wipe> [I<--pool> I<pool-or-uuid>] [I<--algorithm> I<algorithm>]
I<vol-name-or-key-or-path>
Wipe a volume, ensure data previously on the volume is not accessible to Wipe a volume, ensure data previously on the volume is not accessible to
future reads. I<--pool> I<pool-or-uuid> is the name or UUID of the storage future reads. I<--pool> I<pool-or-uuid> is the name or UUID of the storage
pool the volume is in. pool the volume is in.
I<vol-name-or-key-or-path> is the name or key or path of the volume to wipe. I<vol-name-or-key-or-path> is the name or key or path of the volume to wipe.
It is possible to choose different wiping algorithms instead of re-writing
volume with zeroes. This can be done via I<--algorithm> switch.
B<Supported algorithms>
zero - 1-pass all zeroes
nnsa - 4-pass NNSA Policy Letter NAP-14.1-C (XVI-8) for
sanitizing removable and non-removable hard disks:
random x2, 0x00, verify.
dod - 4-pass DoD 5220.22-M section 8-306 procedure for
sanitizing removeable and non-removeable rigid
disks: random, 0x00, 0xff, verify.
bsi - 9-pass method recommended by the German Center of
Security in Information Technologies
(http://www.bsi.bund.de): 0xff, 0xfe, 0xfd, 0xfb,
0xf7, 0xef, 0xdf, 0xbf, 0x7f.
gutmann - The canonical 35-pass sequence described in
Gutmann's paper.
schneier - 7-pass method described by Bruce Schneier in
"Applied Cryptography" (1996): 0x00, 0xff,
random x5.
pfitzner7 - Roy Pfitzner's 7-random-pass method: random x7.
pfitzner33 - Roy Pfitzner's 33-random-pass method: random x33.
random - 1-pass pattern: random.
=item B<vol-dumpxml> [I<--pool> I<pool-or-uuid>] I<vol-name-or-key-or-path> =item B<vol-dumpxml> [I<--pool> I<pool-or-uuid>] I<vol-name-or-key-or-path>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册