Search
Varnish Enterprise

Total Encryption (crypto)

Description

Varnish Total Encryption provides cache encryption and a VCL based crypto API. Varnish Total Encryption uses an innovative dual key encryption algorithm with one key securely stored in the Linux kernel and the other key generated from the client request. No keys are ever stored in Varnish or in cache and every object has its own unique key.

Further information can be found here: Varnish Total Encryption.

Examples

Basic Example

Generate a cookie based random ID string (UUID).

import crypto;
import cookieplus;

sub vcl_deliver
{
  # ID format: 5a580f83ff659c9554b91e06c90ae7f1
  if (!cookieplus.get("id")) {
    cookieplus.setcookie_add("id", crypto.hex_encode(crypto.urandom()));
    cookieplus.setcookie_write();
  }

  # ID format: 06d1ee05-ad8d-0e22-563f-8f9bd5b59bec
  if (!cookieplus.get("id2")) {
    cookieplus.setcookie_add("id2", crypto.uuid_v4());
    cookieplus.setcookie_write();
  }
}

Memory Encryption

Encrypting malloc, file, and mse (non-persistence) using a randomly generated master key.

include "total-encryption/random_key.vcl";

Disk Encryption

Encrypting mse with persistence enabled using a local secret key.

First, generate a new secret key:

$ cat /dev/urandom | head -c 1024 > /etc/varnish/disk_secret
$ sudo chmod 600 /etc/varnish/disk_secret
$ sudo chown root: /etc/varnish/disk_secret

Add the key to the varnishd systemd unit configuration. This allows the disk_secret to be securely read via the varnishd jail configuration:

ExecStart=/usr/sbin/varnishd ... -E /etc/varnish/disk_secret

For more information on how to do this, please see our systemd reference.

Use the secret key to encrypt cache:

include "total-encryption/secret_key.vcl";

Header Encryption

When using one of the above Total Encryption includes, you can optionally encrypt headers with the following VCL:

sub vcl_backend_response {
  # Encrypt beresp.http.Content-Type
  set beresp.http.Content-Type = crypto.hex_encode(crypto.aes_encrypt(beresp.http.Content-Type));
}

sub vcl_deliver {
  # Decrypt resp.http.Content-Type
  if (resp.http.Content-Type != "") {
    set resp.http.Content-Type = crypto.aes_decrypt(crypto.hex_decode(resp.http.Content-Type));
  }
}

Skipping Encryption

Use crypto.aes_skip_response() to skip encryption or decryption in sub vcl_backend_response or sub vcl_deliver.

sub vcl_backend_response {
  if (beresp.http.Content-Type ~ "video") {
    crypto.aes_skip_response();
  }
}

Alternate Encryption Cipher

By default Varnish Total Encryption uses Cipher Block Chaining (CBC) AES encryption. On some systems, Propagating Cipher Block Chaining (PCBC) is available hardware accelerated. If so, use the following VCL to use PCBC AES encryption:

sub vcl_init {
  te_opts.set("algorithm", "pcbc(aes)");
}

API

blob

BLOB blob(STRING value)

Cast a STRING to a BLOB. If using a STRING based secret, this function must be used to cast the secret to a BLOB.

Arguments:

  • value accepts type STRING

Type: Function

Returns: Blob

string

STRING string(BLOB value)

Cast a BLOB to a STRING.

Arguments:

  • value accepts type BLOB

Type: Function

Returns: String

hex_encode

STRING hex_encode(BLOB value)

Hex encode a binary (BLOB) value. Lowercase hex is used.

Arguments:

  • value accepts type BLOB

Type: Function

Returns: String

hex_decode

BLOB hex_decode(STRING value)

Hex decode a hex string into a binary BLOB.

Arguments:

  • value accepts type STRING

Type: Function

Returns: Blob

base64_encode

STRING base64_encode(BLOB value)

Base64 encode a binary (BLOB) value.

Arguments:

  • value accepts type BLOB

Type: Function

Returns: String

base64_decode

BLOB base64_decode(STRING value)

Base64 decode a string into a binary BLOB.

Arguments:

  • value accepts type STRING

Type: Function

Returns: Blob

urandom

BLOB urandom(INT bytes = 16)

Get bytes from /dev/urandom.

Arguments:

  • bytes accepts type INT with a default value of 16 optional

Type: Function

Returns: Blob

secret

BLOB secret()

Get the contents of the secret file from the command line parameter -E. If using a Total Encryption secret key, this value will be scrubbed and the return value will be empty.

Arguments: None

Type: Function

Returns: Blob

hash_part

VOID hash_part(ENUM {md5,sha1,sha224,sha256,sha384,sha512} algorithm, STRING part)

Arguments:

  • part accepts type STRING

  • algorithm is an ENUM that accepts values of md5, sha1, sha224, sha256, sha384, and sha512

Type: Function

Returns: None

hash

BLOB hash(ENUM {md5,sha1,sha224,sha256,sha384,sha512} algorithm, STRING value)

Arguments:

  • value accepts type STRING

  • algorithm is an ENUM that accepts values of md5, sha1, sha224, sha256, sha384, and sha512

Type: Function

Returns: Blob

hmac_init

OBJECT hmac_init(ENUM {sha1,sha224,sha256,sha384,sha512} algorithm, STRING cache_name = "")

Create a new HMAC signing object. This object using the Linux Kernel Crypto API for signing. The HMAC key used is securely stored in the kernel and not kept in the Varnish address space.

Arguments:

  • cache_name accepts type STRING with a default value of empty. optional

  • algorithm is an ENUM that accepts values of sha1, sha224, sha256, sha384, and sha512

Type: Object

Returns: Object.

.set_key

VOID .set_key(BLOB key)

Set the key of an HMAC signing object. Can only be used in sub vcl_init.

Arguments:

  • key accepts type BLOB

Type: Method

Returns: None

.add_string

VOID .add_string(STRING value)

Add a string to the HMAC.

Arguments:

  • value accepts type STRING

Type: Method

Returns: None

.add_blob

VOID .add_blob(BLOB value)

Add a blob to the HMAC.

Arguments:

  • value accepts type BLOB

Type: Method

Returns: None

.get

BLOB .get()

The the HMAC value. After calling, the HMAC state is reset.

Arguments: None

Type: Method

Returns: Blob

hmac

BLOB hmac(ENUM {sha1,sha224,sha256,sha384,sha512} algorithm, BLOB key, STRING value)

Perform an HMAC operation.

Arguments:

  • key accepts type BLOB

  • value accepts type STRING

  • algorithm is an ENUM that accepts values of sha1, sha224, sha256, sha384, and sha512

Type: Function

Returns: Blob

aes_key

VOID aes_key(BLOB key, BLOB salt = 0, STRING algorithm = "")

Set an AES key. This is request scope only. The Linux Kernel Crypto API is used.

The key must be either 128, 192, or 256 bit. The salt (iv) must be 16 bytes, block size is 16 bytes and padding is NULL bytes

Note: If using Total Encryption, this can be safely used in sub vcl_recv only. This is automatically called in sub vcl_backend_response and sub vcl_deliver with a key unique to the request. Please contact support for advanced usage.

Arguments:

  • key accepts type BLOB

  • salt accepts type BLOB with a default value of 0 optional

  • algorithm accepts type STRING with a default value of empty. optional

Type: Function

Returns: None

aes_encrypt

BLOB aes_encrypt(STRING value)

AES encrypt a value. The block size is 16 bytes and the result is NULL padded.

Arguments:

  • value accepts type STRING

Type: Function

Returns: Blob

aes_decrypt

STRING aes_decrypt(BLOB value)

AES decrypt a value. The block size must be 16 bytes.

Arguments:

  • value accepts type BLOB

Type: Function

Returns: String

aes_get_length

INT aes_get_length()

Get the padding length.

Arguments: None

Type: Function

Returns: Int

aes_set_length

VOID aes_set_length(INT length)

Set the padding length.

Arguments:

  • length accepts type INT

Type: Function

Returns: None

aes_encrypt_response

VOID aes_encrypt_response()

Encrypt a response.

Arguments: None

Type: Function

Returns: None

aes_decrypt_response

VOID aes_decrypt_response()

Decrypt a response.

Arguments: None

Type: Function

Returns: None

aes_skip_response

VOID aes_skip_response()

Skip a response.

Arguments: None

Type: Function

Returns: None

uuid_v4

STRING uuid_v4()

Get a version 4 UUID.

Arguments: None

Type: Function

Returns: String

Availability

The crypto VMOD is available in Varnish Enterprise version 6.0.0r0 and later.