Commit eec1a6d2 authored by Geoff Simmons's avatar Geoff Simmons

Use of secure memory for symmetric objects is now false by default.

Update the docs to describe what affects how much secure memory may
be needed, and also to describe the limitations imposed by
PTHREAD_KEYS_MAX.
parent 153a76d9
......@@ -133,10 +133,11 @@ Varnish:
are lowered when secure memory is initialized. This applies to the
varnishd child process.
The use of secure memory is enabled by default. With the VMOD, you can
specify the use of secure memory with the ``secure`` flag, and
configure the size of the pool, or disable secure memory, using the
``init()`` function, as described below.
The use of secure memory is disabled by default. With the VMOD, you
can specify the use of secure memory by setting the ``secure`` flag to
``true`` in a constructor for symmetric encryption, and configure the
size of the pool, or disable secure memory, using the ``init()``
function, as described below.
libgcrypt logging
-----------------
......@@ -199,7 +200,7 @@ hence has the same effect as calling ``init(DISABLE_SECMEM)``. If
secure memory is enabled, libgcrypt imposes a minimum size for the
pool (16 KiB for libgcrypt 1.6.3), so any value of ``n`` that is
smaller than the minimum will result in the minimum allocation. Since
the default value of ``n`` is 1, you can specify the minimum size by
the default value of ``n`` is 1B, you can specify the minimum size by
calling ``init(INIT_SECMEM)`` without the ``n`` parameter.
``DISABLE_SECMEM`` disables secure memory; when secure memory is
......@@ -271,7 +272,7 @@ symmetric
::
new OBJ = symmetric(ENUM {AES,AES128,RIJNDAEL,RIJNDAEL128,AES192,RIJNDAEL192,AES256,RIJNDAEL256} cipher, ENUM {ECB,CFB,CBC,OFB,CTR} mode, ENUM {PKCS7,ISO7816,X923,NONE} padding="PKCS7", BLOB key, BOOL secure=1, BOOL cbc_cts=0)
new OBJ = symmetric(ENUM {AES,AES128,RIJNDAEL,RIJNDAEL128,AES192,RIJNDAEL192,AES256,RIJNDAEL256} cipher, ENUM {ECB,CFB,CBC,OFB,CTR} mode, ENUM {PKCS7,ISO7816,X923,NONE} padding="PKCS7", BLOB key, BOOL secure=0, BOOL cbc_cts=0)
Create an object for encryption and decryption with symmetric ciphers.
Currently, only AES is supported, with key lengths 128, 192 and 256.
......@@ -316,7 +317,7 @@ be correct for the cipher that is to be used; for example, 16 bytes
for AES-128.
If the ``secure`` flag is true, then secure memory is used by the
internal libgcrypt structures created for the object. True by default.
internal libgcrypt structures created for the object. False by default.
If the ``cbc_cts`` flag is true and ``CBC`` mode is specified, then
CBC is used with ciphertext stealing (and padding is not required).
......@@ -361,18 +362,18 @@ Examples::
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
# Create an object for AES-128 with CTR mode (no padding
# required), using secure memory by default.
# required), not using secure memory by default.
new aes128 = gcrypt.symmetric(AES128, CTR, key=k128.get());
# Create an object for AES-192 with CBC mode and PKCS#7
# padding, not using secure memory.
# padding, using secure memory.
new aes192 = gcrypt.symmetric(AES192, CBC, PKCS7, key=k192.get(),
secure=false);
secure=true);
# Create an object for AES-256 with CBC mode and ciphertext
# stealing (no padding required), using secure memory.
new aes256 = gcrypt.symmetric(AES256, CBC, key=k256.get(),
cbc_cts=true);
cbc_cts=true, secure=true);
}
.. _func_symmetric.encrypt:
......@@ -643,19 +644,49 @@ in the Varnish log, then increase the varnishd parameters
If you choose to use the libgcrypt secure memory feature, then the
size of the pool that is needed depends on the number of VMOD objects
that you create. The default size should be sufficient for typical
use cases, but you may need to configure a larger pool if you are
that you create and the number of threads in which encryption
operations are performed. For each object in each thread, an internal
structure for libgcrypt is created the first time an encryption or
decryption is attempted; the same structure is then re-used for all
other operations in the same thread. These structures are deallocated
when the thread exits.
If secure memory has been specified for the VMOD object, then these
internal structures are allocated from the secure memory pool. So you
may need to configure a large pool if you are running many worker
threads to handle a heavy load for Varnish, and more so if you are
using many objects.
Recall that the number of worker threads run by Varnish is controlled
by the varnishd parameters ``thread_pools``, ``thread_pool_min`` and
``thread_pool_max``; this in turn affects how much secure memory will
need to be available for each object in each thread. ``thread_pools``
determines how many thread pools there are, and for each pool, at
least ``thread_pool_min`` will always be started. More threads may be
started to respond to increasing load, up to the maximum given by
``thread_pool_max`` for each thread. As load decreases (that is, when
threads become idle for time given by ``thread_pool_timeout``),
threads will be stopped until the minimum ``thread_pool_min`` is
reached.
The VMOD uses pthread keys (see ``pthread_key_create(3)``) to locate
the thread-specific data for a symmetric encryption object. A key must
be created for each object in each active VCL instance, and the number
of keys that can be created is subject to the limit defined by
``PTHREAD_KEYS_MAX`` (1024 for current Linux versions); so this limits
the number of ``symmetric`` objects that can exist in active VCL
instances. When an object is de-allocated, its key is deleted, and
then no longer counts against the maximum.
Note that when a VCL instance is unloaded at runtime (so as to load a
new instance), the objects allocated for the unloaded instance are not
de-allocated until that instance enters the cold state, by default
after 5 minutes in Varnish 5.1 (determined by the varnishd parameter
``vcl_cooldown``); so the use of the secure memory pool accumulates
during this time. You can bring about an earlier de-allocation, and
hence reduce the use of the secure memory pool, by shortening the
``vcl_cooldown`` period, or by using the CLI command ``vcl.discard``
to explicitly remove previous VCL instances.
``vcl_cooldown``); so the number of pthread keys accumulates during
this time. You can bring about an earlier de-allocation, and hence
reduce the use of the pthread keys, by shortening the ``vcl_cooldown``
period, or by using the CLI command ``vcl.discard`` to explicitly
remove previous VCL instances.
SECURITY
========
......
......@@ -2,13 +2,11 @@
varnishtest "AES"
# Initialize to use 64KiB secure memory
varnish v1 -vcl {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
backend b { .host = "${bad_ip}"; }
sub vcl_init {
gcrypt.init(INIT_SECMEM, 64KB);
gcrypt.init(FINISH);
}
} -start
......@@ -847,3 +845,58 @@ client c1 {
expect resp.http.cbc-iv ~ "^[[:xdigit:]]{32}$"
expect resp.http.cbc-plaintext == "000102030405060708090a0b0c0d0e0f"
} -run
# Repeat the previous test using secure memory
varnish v1 -vcl {
import blobcode;
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new k1 = blobcode.blob(HEX, "000102030405060708090a0b0c0d0e0f");
new ctr = gcrypt.symmetric(AES, CTR, key=k1.get(), secure=true);
new cbc = gcrypt.symmetric(AES, CBC, key=k1.get(),
cbc_cts=true, secure=true);
new p1 = blobcode.blob(HEX, "000102030405060708090a0b0c0d0e0f");
}
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
set resp.http.ctr-ciphertext
= blobcode.encode(HEXLC,
ctr.encrypt(p1.get(),
ctr=gcrypt.random(NONCE, 16B)));
set resp.http.ctr-ctr
= blobcode.encode(HEXLC, gcrypt.random());
set resp.http.ctr-plaintext
= blobcode.encode(HEXLC,
ctr.decrypt(blobcode.decode(HEX, resp.http.ctr-ciphertext),
ctr=blobcode.decode(HEX, resp.http.ctr-ctr)));
set resp.http.cbc-ciphertext
= blobcode.encode(HEXLC,
cbc.encrypt(p1.get(),
iv=gcrypt.random(STRONG, 16B)));
set resp.http.cbc-iv
= blobcode.encode(HEXLC, gcrypt.random());
set resp.http.cbc-plaintext
= blobcode.encode(HEXLC,
cbc.decrypt(blobcode.decode(HEX, resp.http.cbc-ciphertext),
iv=blobcode.decode(HEX, resp.http.cbc-iv)));
return(deliver);
}
}
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.ctr-ciphertext ~ "^[[:xdigit:]]{32}$"
expect resp.http.ctr-ctr ~ "^[[:xdigit:]]{32}$"
expect resp.http.ctr-plaintext == "000102030405060708090a0b0c0d0e0f"
expect resp.http.cbc-ciphertext ~ "^[[:xdigit:]]{32}$"
expect resp.http.cbc-iv ~ "^[[:xdigit:]]{32}$"
expect resp.http.cbc-plaintext == "000102030405060708090a0b0c0d0e0f"
} -run
......@@ -116,10 +116,11 @@ Varnish:
are lowered when secure memory is initialized. This applies to the
varnishd child process.
The use of secure memory is enabled by default. With the VMOD, you can
specify the use of secure memory with the ``secure`` flag, and
configure the size of the pool, or disable secure memory, using the
``init()`` function, as described below.
The use of secure memory is disabled by default. With the VMOD, you
can specify the use of secure memory by setting the ``secure`` flag to
``true`` in a constructor for symmetric encryption, and configure the
size of the pool, or disable secure memory, using the ``init()``
function, as described below.
libgcrypt logging
-----------------
......@@ -166,7 +167,7 @@ hence has the same effect as calling ``init(DISABLE_SECMEM)``. If
secure memory is enabled, libgcrypt imposes a minimum size for the
pool (16 KiB for libgcrypt 1.6.3), so any value of ``n`` that is
smaller than the minimum will result in the minimum allocation. Since
the default value of ``n`` is 1, you can specify the minimum size by
the default value of ``n`` is 1B, you can specify the minimum size by
calling ``init(INIT_SECMEM)`` without the ``n`` parameter.
``DISABLE_SECMEM`` disables secure memory; when secure memory is
......@@ -234,7 +235,7 @@ Examples::
$Object symmetric(ENUM {AES, AES128, RIJNDAEL, RIJNDAEL128, AES192, RIJNDAEL192,
AES256, RIJNDAEL256} cipher, ENUM {ECB, CFB, CBC, OFB, CTR}
mode, ENUM {PKCS7, ISO7816, X923, NONE} padding="PKCS7",
BLOB key, BOOL secure=1, BOOL cbc_cts=0)
BLOB key, BOOL secure=0, BOOL cbc_cts=0)
Create an object for encryption and decryption with symmetric ciphers.
Currently, only AES is supported, with key lengths 128, 192 and 256.
......@@ -279,7 +280,7 @@ be correct for the cipher that is to be used; for example, 16 bytes
for AES-128.
If the ``secure`` flag is true, then secure memory is used by the
internal libgcrypt structures created for the object. True by default.
internal libgcrypt structures created for the object. False by default.
If the ``cbc_cts`` flag is true and ``CBC`` mode is specified, then
CBC is used with ciphertext stealing (and padding is not required).
......@@ -324,18 +325,18 @@ Examples::
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
# Create an object for AES-128 with CTR mode (no padding
# required), using secure memory by default.
# required), not using secure memory by default.
new aes128 = gcrypt.symmetric(AES128, CTR, key=k128.get());
# Create an object for AES-192 with CBC mode and PKCS#7
# padding, not using secure memory.
# padding, using secure memory.
new aes192 = gcrypt.symmetric(AES192, CBC, PKCS7, key=k192.get(),
secure=false);
secure=true);
# Create an object for AES-256 with CBC mode and ciphertext
# stealing (no padding required), using secure memory.
new aes256 = gcrypt.symmetric(AES256, CBC, key=k256.get(),
cbc_cts=true);
cbc_cts=true, secure=true);
}
$Method BLOB .encrypt(BLOB plaintext, BLOB iv=0, BLOB ctr=0)
......@@ -572,19 +573,49 @@ in the Varnish log, then increase the varnishd parameters
If you choose to use the libgcrypt secure memory feature, then the
size of the pool that is needed depends on the number of VMOD objects
that you create. The default size should be sufficient for typical
use cases, but you may need to configure a larger pool if you are
that you create and the number of threads in which encryption
operations are performed. For each object in each thread, an internal
structure for libgcrypt is created the first time an encryption or
decryption is attempted; the same structure is then re-used for all
other operations in the same thread. These structures are deallocated
when the thread exits.
If secure memory has been specified for the VMOD object, then these
internal structures are allocated from the secure memory pool. So you
may need to configure a large pool if you are running many worker
threads to handle a heavy load for Varnish, and more so if you are
using many objects.
Recall that the number of worker threads run by Varnish is controlled
by the varnishd parameters ``thread_pools``, ``thread_pool_min`` and
``thread_pool_max``; this in turn affects how much secure memory will
need to be available for each object in each thread. ``thread_pools``
determines how many thread pools there are, and for each pool, at
least ``thread_pool_min`` will always be started. More threads may be
started to respond to increasing load, up to the maximum given by
``thread_pool_max`` for each thread. As load decreases (that is, when
threads become idle for time given by ``thread_pool_timeout``),
threads will be stopped until the minimum ``thread_pool_min`` is
reached.
The VMOD uses pthread keys (see ``pthread_key_create(3)``) to locate
the thread-specific data for a symmetric encryption object. A key must
be created for each object in each active VCL instance, and the number
of keys that can be created is subject to the limit defined by
``PTHREAD_KEYS_MAX`` (1024 for current Linux versions); so this limits
the number of ``symmetric`` objects that can exist in active VCL
instances. When an object is de-allocated, its key is deleted, and
then no longer counts against the maximum.
Note that when a VCL instance is unloaded at runtime (so as to load a
new instance), the objects allocated for the unloaded instance are not
de-allocated until that instance enters the cold state, by default
after 5 minutes in Varnish 5.1 (determined by the varnishd parameter
``vcl_cooldown``); so the use of the secure memory pool accumulates
during this time. You can bring about an earlier de-allocation, and
hence reduce the use of the secure memory pool, by shortening the
``vcl_cooldown`` period, or by using the CLI command ``vcl.discard``
to explicitly remove previous VCL instances.
``vcl_cooldown``); so the number of pthread keys accumulates during
this time. You can bring about an earlier de-allocation, and hence
reduce the use of the pthread keys, by shortening the ``vcl_cooldown``
period, or by using the CLI command ``vcl.discard`` to explicitly
remove previous VCL instances.
SECURITY
========
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment