.It Fa hash
Buffer for the output hash.
.It Fa hash_size
-The length of the output
-.Fa hash
-in bytes.
+The length of the output hash, in bytes.
This argument should be set to 16, 32 or 64 for compatibility with the
.Fn crypto_verify*
constant time comparison functions.
.Xr crypto_wipe 3monocypher
after being hashed.
.It Fa password_size
-the length of
-.Fa password .
+The length of
+.Fa password ,
+in bytes.
.It Fa salt
-a password salt.
+A password salt.
This should be filled with random bytes, generated separately for each
password to be hashed.
.It Fa salt_size
-the length of
+The length of
.Fa salt ,
in bytes.
Must be at least 8.
16 is recommended.
.It Fa key
-a key to use in the hash.
+A key to use in the hash.
Can be
.Dv NULL
if
Note: changing the key requires hashing the user's password,
which is only possible upon user login.
.It Fa key_size
-the length of the key, in bytes.
+The length of the key, in bytes.
Must be zero if there is no key.
.It Fa ad
-additional data.
+Additional data.
This is additional data that goes into the hash, similar to the
authenticated encryption with authenticated data (AEAD) construction in
.Xr crypto_aead_lock 3monocypher .
.Fa ad_size
is zero.
.It Fa ad_size
-the length of
-.Fa ad .
+Ahe length of
+.Fa ad ,
+in bytes.
.El
.Pp
The output hash must not overlap with the work area, or it will be
This example shows how to hash a password with the recommended baseline
parameters:
.Bd -literal -offset indent
-uint8_t hash[32], /* output hash */
-const uint8_t *password; /* user's password */
-uint8_t password_size; /* password length */
-const uint8_t salt[16]; /* random salt */
+uint8_t hash[32]; /* Output hash */
+const uint8_t *password; /* User's password */
+uint8_t password_size; /* Password length */
+const uint8_t salt[16]; /* Random salt */
const uint32_t nb_blocks = 100000; /* 100 megabytes */
const uint32_t nb_iterations = 3; /* 3 iterations */
-void *work_area = malloc(nb_blocks * 1024); /* work area */
+void *work_area = malloc(nb_blocks * 1024); /* Work area */
if (work_area == NULL) {
- /* handle malloc() failure */
+ /* Handle malloc() failure */
}
crypto_argon2i(hash, 32,
work_area, nb_blocks, nb_iterations,
salt, 16);
/* Wipe secrets if they are no longer needed */
crypto_wipe(password, password_size);
+free(work_area);
.Ed
.Sh SEE ALSO
.Xr crypto_lock 3monocypher ,
.Xr crypto_wipe 3monocypher
once they are done with it.
.It Fa key_size
-Length of the
-.Fa key
-in bytes.
+Length of the secret key, in bytes.
Must be between 0 and 64.
32 is a good default.
.It Fa message
.Fa hash
argument.
.It Fa message_size
-The length of the message in bytes.
+The length of the message, in bytes.
.El
.Ss Direct interface
The direct interface has two functions,
users can specify the size of the hash, and use a secret key to
make the hash unpredictable \(en useful for message authentication
codes.
-Even when using a
-.Fa key ,
-you do not have to wipe the context struct with
+Even when using a key, you do not have to wipe the context struct with
.Xr crypto_wipe 3monocypher .
.Ss Incremental interface
The incremental interface is useful for handling streams of data or
.Sh RETURN VALUES
These functions return nothing.
.Sh EXAMPLES
-Hashes a message all at once.
+Hashing a message all at once:
.Bd -literal -offset indent
uint8_t hash [ 64]; /* Output hash (64 bytes) */
uint8_t message[500]; /* Message to hash */
crypto_blake2b(hash, message, 500);
+/* Wipe secrets if they are no longer needed */
+crypto_wipe(message, 500);
.Ed
.Pp
-Computes a message authentication code all at once.
+Computing a message authentication code all at once:
.Bd -literal -offset indent
uint8_t hash [ 64]; /* Output hash (between 1 and 64 bytes) */
uint8_t key [ 32]; /* Optional key (between 0 and 64 bytes) */
uint8_t message[500]; /* Message to hash */
crypto_blake2b_general(hash, 64, key, 32, message, 500);
-/* Wipe the key. */
+/* Wipe secrets if they are no longer needed */
+crypto_wipe(message, 500);
crypto_wipe(key, 32);
.Ed
.Pp
-Hashes a message incrementally.
+Hashing a message incrementally:
.Bd -literal -offset indent
uint8_t hash [ 64]; /* Output hash (64 bytes) */
uint8_t message[500]; /* Message to hash */
crypto_blake2b_ctx ctx;
-crypto_blake2b_init (&ctx);
+crypto_blake2b_init(&ctx);
for (size_t i = 0; i < 500; i += 100) {
crypto_blake2b_update(&ctx, message + i, 100);
+ /* Wipe secrets if they are no longer needed */
+ crypto_wipe(message + i, 100);
}
-crypto_blake2b_final (&ctx, hash);
+crypto_blake2b_final(&ctx, hash);
.Ed
.Pp
-Computes a message authentication code incrementally.
+Computing a message authentication code incrementally:
.Bd -literal -offset indent
uint8_t hash [ 64]; /* Output hash (between 1 and 64 bytes) */
uint8_t key [ 32]; /* Optional key (between 0 and 64 bytes) */
uint8_t message[500]; /* Message to hash */
crypto_blake2b_ctx ctx;
crypto_blake2b_general_init(&ctx, 64, key, 32);
-/* Wipe the key. */
+/* Wipe the key */
crypto_wipe(key, 32);
for (size_t i = 0; i < 500; i += 100) {
crypto_blake2b_update(&ctx, message + i, 100);
+ /* Wipe secrets if they are no longer needed */
+ crypto_wipe(message + i, 100);
}
-crypto_blake2b_final (&ctx, hash);
+crypto_blake2b_final(&ctx, hash);
.Ed
.Sh SEE ALSO
.Xr crypto_key_exchange 3monocypher ,
This function returns nothing.
It cannot fail.
.Sh EXAMPLES
-Simple hash.
+Simple hash:
.Bd -literal -offset indent
-const uint8_t key[32] /* Must have enough entropy */
-const uint8_t in [16] /* Does not have to be random */
-uint8_t out[32] /* Will be random iff the above holds */
+const uint8_t key[32]; /* Must have enough entropy */
+const uint8_t in [16]; /* Does not have to be random */
+uint8_t out[32]; /* Will be random iff the above holds */
crypto_chacha20_H(out, key, in);
/* Wipe secrets if they are no longer needed */
crypto_wipe(key, 32);
It is allowed to be
.Dv NULL ,
in which case it will be interpreted as an all zero input.
-The cipher_text will then contain the raw Chacha20 stream.
+.Fa cipher_text
+will then contain the raw Chacha20 stream.
.It Fa cipher_text
The encrypted message.
.It Fa text_size
The size of both
.Fa plain_text and
-.Fa cipher_text .
+.Fa cipher_text ,
+in bytes.
.It Fa stream
-the raw Chacha20 stream.
+The raw Chacha20 stream.
.It Fa stream_size
-The size of the stream.
+The size of the stream, in bytes.
.It Fa ctr
The number of 64-byte blocks since the beginning of the stream.
.El
behaviour.
.Pp
.Fn crypto_chacha20_encrypt
-encrypts the
+encrypts
.Fa plain_text
by XORing it with a pseudo-random stream of
numbers, seeded by the provided
.Pp
Since XOR is its own inverse, decryption is the same operation as
encryption.
-To decrypt the
-.Fa cipher_text ,
-encrypt it again with the same
-.Fa key
-and
-.Fa nonce .
+To decrypt the cipher text, encrypt it again with the same key and nonce.
You will likely want to wipe the key and context when you are done with
encryption or decryption.
Use
7539 (not implemented in Monocypher because of its complexity and
limitations).
Be careful when using this not to accidentally reuse parts of the
-random stream.
-This would destroy confidentiality.
+random stream as that would destroy confidentiality.
.Sh RETURN VALUES
These functions return nothing.
They cannot fail.
.Sh EXAMPLES
Simple encryption:
.Bd -literal -offset indent
-const uint8_t key [ 32]; /* Secret random key */
-const uint8_t nonce [ 24]; /* Unique nonce (possibly random) */
-const uint8_t plain_text [500]; /* Message to be encrypted */
-uint8_t cipher_text[500]; /* Will be the encrypted message */
+const uint8_t key [ 32]; /* Secret random key */
+const uint8_t nonce [ 24]; /* Unique nonce (possibly random) */
+const uint8_t plain_text [500]; /* Message to be encrypted */
+uint8_t cipher_text[500]; /* Will be the encrypted message */
crypto_chacha_ctx ctx;
crypto_chacha20_x_init(&ctx, key, nonce);
crypto_chacha20_encrypt(&ctx, cipher_text, plain_text, 500);
/* Wipe secrets if they are no longer needed */
-crypto_wipe(key, sizeof(key));
+crypto_wipe(key, 32);
crypto_wipe(&ctx, sizeof(ctx));
-crypto_wipe(plain_text, sizeof(plain_text));
+crypto_wipe(plain_text, 500);
.Ed
.Pp
To decrypt the above:
.Bd -literal -offset indent
-const uint8_t key [ 32]; /* Same key as above */
-const uint8_t nonce [ 24]; /* Same nonce as above */
-const uint8_t cipher_text[500]; /* Encrypted message */
-uint8_t plain_text [500]; /* Will be the decrypted message */
+const uint8_t key [ 32]; /* Same key as above */
+const uint8_t nonce [ 24]; /* Same nonce as above */
+const uint8_t cipher_text[500]; /* Encrypted message */
+uint8_t plain_text [500]; /* Will be the decrypted message */
crypto_chacha_ctx ctx;
crypto_chacha20_x_init(&ctx, key, nonce);
crypto_chacha20_encrypt(&ctx, plain_text, cipher_text, 500);
/* Wipe secrets if they are no longer needed */
-crypto_wipe(key, sizeof(key));
+crypto_wipe(key, 32);
crypto_wipe(&ctx, sizeof(ctx));
/* The plain text likely needs to be processed before you wipe it */
crypto_wipe(plain_text, 500);
.Pp
Incremental encryption:
.Bd -literal -offset indent
-const uint8_t key [ 32]; /* Secret random key */
-const uint8_t nonce [ 24]; /* Unique nonce (possibly random) */
-const uint8_t plain_text [500]; /* Message to be encrypted */
-uint8_t cipher_text[500]; /* Will be the encrypted message */
+const uint8_t key [ 32]; /* Secret random key */
+const uint8_t nonce [ 24]; /* Unique nonce (possibly random) */
+const uint8_t plain_text [500]; /* Message to be encrypted */
+uint8_t cipher_text[500]; /* Will be the encrypted message */
crypto_chacha_ctx ctx;
crypto_chacha20_x_init(&ctx, key, nonce);
for(int i = 0; i < 500; i += 100) {
crypto_chacha20_encrypt(&ctx, cipher_text+i, plain_text+i, 100);
}
/* Wipe secrets if they are no longer needed */
-crypto_wipe(key, sizeof(key));
+crypto_wipe(key, 32);
crypto_wipe(&ctx, sizeof(ctx));
-crypto_wipe(plain_text, sizeof(plain_text));
+crypto_wipe(plain_text, 500);
.Ed
.Pp
Simple encryption with a small,
.Em not
random nonce:
.Bd -literal -offset indent
-const uint8_t key [ 32]; /* Secret, random key */
-const uint8_t nonce [ 8]; /* Unique nonce (NOT random) */
-const uint8_t plain_text [500]; /* Message to be encrypted */
+const uint8_t key [ 32]; /* Secret, random key */
+const uint8_t nonce [ 8]; /* Unique nonce (NOT random) */
+const uint8_t plain_text [500]; /* Message to be encrypted */
+uint8_t cipher_text[500]; /* Will be the encrypted message */
crypto_chacha_ctx ctx;
crypto_chacha20_init(&ctx, key, nonce);
crypto_chacha20_encrypt(&ctx, cipher_text, plain_text, 500);
-crypto_wipe(key, sizeof(key));
-crypto_wipe(&ctx, sizeof(ctx));
/* Wipe secrets if they are no longer needed */
-crypto_wipe(key, sizeof(key));
+crypto_wipe(key, 32);
crypto_wipe(&ctx, sizeof(ctx));
-crypto_wipe(plain_text, sizeof(plain_text));
+crypto_wipe(plain_text, 500);
.Ed
.Pp
Encryption by jumping around (do not do that, this is only meant to show
.Fn crypto_chacha20_set_ctr
works):
.Bd -literal -offset indent
-const uint8_t key [ 32]; /* Secret random key */
-const uint8_t nonce [ 24]; /* Unique nonce (possibly random) */
-const uint8_t plain_text [500]; /* Message to be encrypted */
-uint8_t cipher_text[500]; /* Will be the encrypted message */
+const uint8_t key [ 32]; /* Secret random key */
+const uint8_t nonce [ 24]; /* Unique nonce (possibly random) */
+const uint8_t plain_text [500]; /* Message to be encrypted */
+uint8_t cipher_text[500]; /* Will be the encrypted message */
crypto_chacha_ctx ctx;
crypto_chacha20_x_init(&ctx, key, nonce);
/* Encrypt the second part of the message first... */
crypto_chacha20_set_ctr(&ctx, 0);
crypto_chacha20_encrypt(&ctx, cipher_text, plain_text, 3 * 64);
/* Wipe secrets if they are no longer needed */
-crypto_wipe(key, sizeof(key));
+crypto_wipe(key, 32);
crypto_wipe(&ctx, sizeof(ctx));
-crypto_wipe(plain_text, sizeof(plain_text));
+crypto_wipe(plain_text, 500);
.Ed
.Sh SEE ALSO
.Xr crypto_lock 3monocypher ,
.Fc
.Ft void
.Fo crypto_x25519_public_key
-.Fa "uint8_t public_key[32]"
-.Fa "const uint8_t secret_key[32]"
+.Fa "uint8_t your_public_key[32]"
+.Fa "const uint8_t your_secret_key[32]"
.Fc
.Sh DESCRIPTION
.Fn crypto_key_exchange
The public keys are different, and revealing both may leak information.
.It Fa their_public_key
The public key of the other party.
-.It Fa public_key
-The public key, generated from the
+.It Fa your_public_key
+Your public key, generated from
.Fa secret_key
with
.Fn crypto_x25519_public_key .
-.It Fa secret_key
-A 32-byte random number, known only to you.
.El
.Sh RETURN VALUES
Some public keys force the shared key to a known constant.
about random number generation (use your operating system's random
number generator).
.It Fa mac
-a 16-byte
-.Em message authentication code (MAC) ,
-that can only be produced by someone who knows the session key.
+A 16-byte
+.Em message authentication code
+(MAC), that can only be produced by someone who knows the session key.
This guarantee cannot be upheld if a nonce has been reused with the
session key, because doing so allows the attacker to learn the
authentication key associated with that nonce.
.It Fa text_size
The size of both
.Fa plain_text and
-.Fa cipher_text .
+.Fa cipher_text ,
+in bytes.
.El
.Pp
The
and
.Fn crypto_unlock .
.It Fa ad_size
-length of the additional data.
+Length of the additional data, in bytes.
.Sy That length is not authenticated.
If the additional data is of variable length, the length should be
appended to
.Sh EXAMPLES
Encryption:
.Bd -literal -offset indent
-const uint8_t key [32]; /* Random, secret session key */
-const uint8_t nonce[24]; /* Use only once per key */
-const uint8_t *plain_text; /* Secret message */
-size_t text_size; /* Message size (NOT secret) */
-uint8_t mac [16]; /* Message authentication code */
-uint8_t *cipher_text; /* Encrypted message */
+const uint8_t key [32]; /* Random, secret session key */
+const uint8_t nonce[24]; /* Use only once per key */
+const uint8_t *plain_text; /* Secret message */
+size_t text_size; /* Message size (NOT secret) */
+uint8_t mac [16]; /* Message authentication code */
+uint8_t *cipher_text; /* Encrypted message */
crypto_lock(mac, cipher_text, key, nonce, plain_text, text_size);
/* Wipe secrets if they are no longer needed */
crypto_wipe(plain_text, text_size);
.Pp
To decrypt the above:
.Bd -literal -offset indent
-const uint8_t key [32]; /* Same as the above */
-const uint8_t nonce[24]; /* Same as the above */
-const uint8_t mac [16]; /* Received from the network */
-const uint8_t *cipher_text; /* Encrypted message */
-size_t text_size; /* Message size (NOT secret) */
-uint8_t *plain_text; /* Secret message */
+const uint8_t key [32]; /* Same as the above */
+const uint8_t nonce[24]; /* Same as the above */
+const uint8_t mac [16]; /* Received from the network */
+const uint8_t *cipher_text; /* Encrypted message */
+size_t text_size; /* Message size (NOT secret) */
+uint8_t *plain_text; /* Secret message */
if (crypto_unlock(plain_text, key, nonce, mac,
cipher_text, text_size)) {
/* The message is corrupted.
.Pp
In-place encryption:
.Bd -literal -offset indent
-const uint8_t key [32]; /* Random, secret session key */
-const uint8_t nonce[24]; /* Use only once per key */
-uint8_t *plain_text; /* Secret message */
-size_t text_size; /* Message size (NOT secret) */
-uint8_t mac [16]; /* Message authentication code */
+const uint8_t key [32]; /* Random, secret session key */
+const uint8_t nonce[24]; /* Use only once per key */
+uint8_t *plain_text; /* Secret message */
+size_t text_size; /* Message size (NOT secret) */
+uint8_t mac [16]; /* Message authentication code */
crypto_lock(mac, plain_text, key, nonce, plain_text, text_size);
/* Wipe secrets if they are no longer needed */
crypto_wipe(key, 32);
.Pp
In-place decryption:
.Bd -literal -offset indent
-const uint8_t key [32]; /* Same as the above */
-const uint8_t nonce[24]; /* Same as the above */
-const uint8_t mac [16]; /* Received from the network */
-uint8_t *text; /* Message to decrypt */
-size_t text_size; /* Message size (NOT secret) */
+const uint8_t key [32]; /* Same as the above */
+const uint8_t nonce[24]; /* Same as the above */
+const uint8_t mac [16]; /* Received from the network */
+uint8_t *text; /* Message to decrypt */
+size_t text_size; /* Message size (NOT secret) */
if (crypto_unlock(text, key, nonce, mac, text, text_size)) {
/* The message is corrupted.
* Wipe key if it is no longer needed,
.Fa mac
argument.
.It Fa message_size
-Size of the message.
+Size of the message, in bytes.
.El
.Ss Direct interface
.Fn crypto_poly1305
.Sh EXAMPLES
To authenticate a message:
.Bd -literal -offset indent
-const uint8_t msg[500]; /* Message to authenticate */
-const uint8_t key[ 32]; /* Random secret key (use only once) */
-uint8_t mac[ 16]; /* Message authentication code (MAC) */
+const uint8_t msg[500]; /* Message to authenticate */
+const uint8_t key[ 32]; /* Random secret key (use only once) */
+uint8_t mac[ 16]; /* Message authentication code (MAC) */
crypto_poly1305(mac, msg, 500, key);
/* Wipe the key */
crypto_wipe(key, 32);
.Pp
To verify the above message:
.Bd -literal -offset indent
-const uint8_t msg [500]; /* Message to verify */
-const uint8_t key [ 32]; /* The above key */
-const uint8_t mac [ 16]; /* The above MAC */
-uint8_t real_mac[ 16]; /* The actual MAC */
+const uint8_t msg [500]; /* Message to verify */
+const uint8_t key [ 32]; /* The above key */
+const uint8_t mac [ 16]; /* The above MAC */
+uint8_t real_mac[ 16]; /* The actual MAC */
crypto_poly1305(real_mac, msg, 500, key);
/* Wipe the key */
crypto_wipe(key, 32);
.Pp
Incremental authentication:
.Bd -literal -offset indent
-const uint8_t msg[500]; /* Message to authenticate */
-const uint8_t key[ 32]; /* Random secret key (use only once) */
-uint8_t mac[ 16]; /* Message authentication code (MAC) */
+const uint8_t msg[500]; /* Message to authenticate */
+const uint8_t key[ 32]; /* Random secret key (use only once) */
+uint8_t mac[ 16]; /* Message authentication code (MAC) */
crypto_poly1305_ctx ctx;
crypto_poly1305_init(&ctx, key);
/* Wipe the key */
Do not use the same private key for both signatures and key exchanges.
The public keys are different, and revealing both may leak information.
.It Fa public_key
-The public key, generated from the
+The public key, generated from
.Fa secret_key
with
.Fn crypto_sign_public_key .
It does not have to in most threat models, because nothing is secret:
everyone knows the public key, and the signature and message are
rarely secret.
-To ascertain the origin of a secret message, use
+If the message needs to be secret, use
.Xr crypto_key_exchange 3monocypher
+and
+.Xr crypto_aead_lock 3monocypher
instead.
.Pp
An incremental interface is available; see
const uint8_t sk [ 32]; /* Secret key */
const uint8_t pk [ 32]; /* Public key (optional) */
const uint8_t message [500]; /* Message to sign */
-uint8_t signature[ 64];
+uint8_t signature[ 64]; /* Output signature */
crypto_sign_ctx ctx;
crypto_sign_init_first_pass(&ctx, sk, pk);
/* Wipe the secret key if no longer needed */
.Pp
Check the above:
.Bd -literal -offset indent
-const uint8_t pk [ 32]; /* Public key */
-const uint8_t message [500]; /* Message to sign */
-const uint8_t signature[ 64];
+const uint8_t pk [ 32]; /* Public key */
+const uint8_t message [500]; /* Message to sign */
+const uint8_t signature[ 64]; /* Signature to check */
crypto_check_ctx ctx;
crypto_check_init(&ctx, signature, pk);
for (size_t i = 0; i < 500; i += 100) {
.Sh DESCRIPTION
Cryptographic operations often require comparison of secrets or values
derived from secrets.
-Standard comparison functions like memcmp tend to exit when they find
-the first difference, leaking information through timing differences.
+Standard comparison functions like
+.Fn memcmp
+tend to exit when they find the first difference, leaking information
+through timing differences.
.Pp
As an example, say a message authentication code (MAC) is sent over the
network along with a message, but the correct MAC is secret.
.Nd wipe data from memory
.Sh SYNOPSIS
.In monocypher.h
-.Ft int
+.Ft void
.Fn crypto_wipe "void *secret" "size_t secret_size"
.Sh DESCRIPTION
.Fn crypto_wipe
The buffer to erase.
.It Fa secret_size
The number of bytes to erase from the buffer.
-This will normally be the entire buffer.
+Normally this is the size of the entire buffer.
.El
.Pp
Monocypher will wipe its context structs when finalizing an operation
/* Wipe secrets if they are no longer needed */
crypto_wipe(your_sk, 32);
-uint8_t shared_keys[64]; /* Two shared session keys */
-uint8_t *key_1 = shared_keys; /* Shared key 1 */
-uint8_t *key_2 = shared_keys + 32; /* Shared key 2 */
+uint8_t shared_keys[64]; /* Two shared session keys */
crypto_blake2b(shared_keys, shared_secret, 32);
-/* Wipe the secret */
+const uint8_t *key_1 = shared_keys; /* Shared key 1 */
+const uint8_t *key_2 = shared_keys + 32; /* Shared key 2 */
+/* Wipe secrets if they are no longer needed */
crypto_wipe(shared_secret, 32);
.Ed
.Sh SEE ALSO
and
.Xr crypto_verify64 3monocypher
compare buffers in constant time.
-This avoids timing attacks when comparing secrets.
-Supported buffer sizes are 16 bytes, 32 bytes, and 64 bytes.
+They should be used to compare secrets to prevent timing attacks.
.Ss Memory wipe
.Xr crypto_wipe 3monocypher
wipes a buffer.
.Xr crypto_sign_init_second_pass 3monocypher ,
.Xr crypto_sign_public_key 3monocypher ,
.Xr crypto_sign_update 3monocypher ,
-.Xr crypto_unlock 3monocypher 3monocypher ,
+.Xr crypto_unlock 3monocypher ,
.Xr crypto_unlock_update 3monocypher ,
.Xr crypto_unlock_final 3monocypher ,
.Xr crypto_verify16 3monocypher ,
This is done by generating temporary keys, then encrypting messages
with them.
.Pp
-This can be generalised: secrets that went through a computer should
-not be compromised when this computer is stolen or infected at a later
-point.
+.Ss Temporary secrets
+If a computer is stolen or infected after handling secret data, those past
+secrets should not be compromised.
.Pp
A first layer of defence is to explicitly wipe secrets as soon as
they are no longer used.
Windows can disable swap for specific buffers with
.Fn VirtualLock .
.Pp
-Note: core dumps cause similar problems.
+Core dumps cause similar problems.
Disable them.
Also beware of suspend to disk (deep sleep mode), which writes all RAM
to disk regardless of swap policy, as well as virtual machine snapshots.