Commit b30ed0a8 authored by Geoff Simmons's avatar Geoff Simmons

Add the init() function

parent b27428ec
Pipeline #172 skipped
......@@ -38,10 +38,20 @@ Privacy Guard cryptographic suite (GnuPG or GPG).
CONTENTS
========
* VOID init(ENUM {INIT_SECMEM,DISABLE_SECMEM,FINISH}, INT)
* symmetric(ENUM {AES,AES128,RIJNDAEL,RIJNDAEL128,AES192,RIJNDAEL192,AES256,RIJNDAEL256}, ENUM {ECB,CFB,CBC,OFB,CTR}, ENUM {PKCS7,ISO7816,X923,NONE}, BLOB, BOOL, BOOL)
* STRING version()
* STRING gcrypt_version()
.. _func_init:
init
----
::
VOID init(ENUM {INIT_SECMEM,DISABLE_SECMEM,FINISH}, INT n=1)
.. _obj_symmetric:
symmetric
......
......@@ -2,6 +2,17 @@
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, 65536);
gcrypt.init(FINISH);
}
} -start
# from selftest() in libgcrypt cipher/rijndael.c
varnish v1 -vcl {
import blobcode;
......@@ -44,7 +55,7 @@ varnish v1 -vcl {
= blobcode.encode(HEXUC, rijndael128.decrypt(c1.get()));
return(deliver);
}
} -start
}
client c1 {
txreq
......
# looks like -*- vcl -*-
varnishtest "init function"
# init() is illegal in every VCL sub except vcl_init
varnish v1 -vcl {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
backend b { .host = "${bad_ip}"; }
sub vcl_recv {
gcrypt.init(FINISH);
return(synth(200));
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error "^vmod gcrypt error: gcrypt.init.. is only legal in vcl_init$"
expect * = End
} -run
# Default initialization of 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);
gcrypt.init(FINISH);
}
}
# Calling init again without restarting Varnish, even after reloading
# VCL, has no effect except to log the fact that initialization is
# already finished.
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, 32768);
gcrypt.init(FINISH);
}
}
logexpect l1 -v v1 -d 1 -g raw -q "Debug" {
expect * 0 Debug "^libgcrypt initialization already finished$"
expect * = Debug "^libgcrypt initialization already finished$"
} -run
# The same is true even if we discard all VCL instances that used the
# VMOD.
varnish v1 -vcl { backend b { .host = "${bad_ip}"; } }
varnish v1 -cli "vcl.discard vcl1"
varnish v1 -cli "vcl.discard vcl2"
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, 32768);
gcrypt.init(FINISH);
}
}
logexpect l1 -v v1 -d 1 -g raw -q "Debug" {
expect * 0 Debug "^libgcrypt initialization already finished$"
expect * = Debug "^libgcrypt initialization already finished$"
} -run
# So now we will have to start new Varnish instances for further
# tests.
varnish v1 -stop
# Initializing secure memory twice cause libgcrypt to log an error,
# but the VMOD can proceed.
varnish v2 -vcl {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
backend b { .host = "${bad_ip}"; }
sub vcl_init {
gcrypt.init(INIT_SECMEM);
gcrypt.init(INIT_SECMEM, 32768);
gcrypt.init(FINISH);
}
} -start
logexpect l2 -v v2 -d 1 -g raw -q "Error" {
expect * 0 Error "^libgcrypt log message follows .ERROR.:"
expect * = Error ".+"
} -run
# Objects cannot be constructed unless initialization is finished.
varnish v2 -stop
varnish v3 -vcl {backend b { .host = "${bad_ip}"; } } -start
varnish v3 -errvcl {libgcrypt initialization not finished in aes constructor} {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new k = blobcode.blob(HEX, "00000000000000000000000000000000");
new aes = gcrypt.symmetric(AES, ECB, key=k.get());
}
}
varnish v3 -vcl {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
gcrypt.init(FINISH);
new k = blobcode.blob(HEX, "00000000000000000000000000000000");
new aes = gcrypt.symmetric(AES, ECB, key=k.get());
}
}
# After initialization but before a restart, a new VCL can construct
# object instances without having to call init(FINISH) again.
varnish v3 -vcl {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new k = blobcode.blob(HEX, "00000000000000000000000000000000");
new aes = gcrypt.symmetric(AES, ECB, key=k.get());
}
}
# Initializing secure memory to 0 bytes is the same as disabling it.
varnish v3 -stop
varnish v4 -vcl {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
backend b { .host = "${bad_ip}"; }
sub vcl_init {
gcrypt.init(INIT_SECMEM, 0);
gcrypt.init(FINISH);
}
} -start
varnish v4 -errvcl {vmod gcrypt error: secure memory not enabled in aes constructor} {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new k = blobcode.blob(HEX, "00000000000000000000000000000000");
new aes = gcrypt.symmetric(AES, ECB, key=k.get(), secure=true);
}
}
# INIT_SECMEM is illegal with bytes < 0.
varnish v4 -stop
varnish v5 -vcl {backend b { .host = "${bad_ip}"; } } -start
varnish v5 -errvcl {INIT_SECMEM number of bytes -1 out of range in gcrypt.init()} {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
backend b { .host = "${bad_ip}"; }
sub vcl_init {
gcrypt.init(INIT_SECMEM, -1);
}
}
# DISABLE_SECMEM
varnish v5 -vcl {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
gcrypt.init(DISABLE_SECMEM);
gcrypt.init(FINISH);
new k = blobcode.blob(HEX, "00000000000000000000000000000000");
new aes = gcrypt.symmetric(AES, ECB, key=k.get(), secure=false);
}
}
varnish v5 -errvcl {vmod gcrypt error: secure memory not enabled in aes constructor} {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new k = blobcode.blob(HEX, "00000000000000000000000000000000");
new aes = gcrypt.symmetric(AES, ECB, key=k.get(), secure=true);
}
}
# Secure memory is enabled by default
varnish v5 -stop
varnish v6 -vcl {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
gcrypt.init(FINISH);
new k = blobcode.blob(HEX, "00000000000000000000000000000000");
new aes = gcrypt.symmetric(AES, ECB, key=k.get(), secure=true);
}
} -start
# If secure memory is enabled and then disabled, or vice versa, then
# the the last setting is valid.
varnish v6 -stop
varnish v7 -vcl {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
gcrypt.init(INIT_SECMEM);
gcrypt.init(DISABLE_SECMEM);
gcrypt.init(FINISH);
new k = blobcode.blob(HEX, "00000000000000000000000000000000");
new aes = gcrypt.symmetric(AES, ECB, key=k.get(), secure=false);
}
} -start
varnish v7 -errvcl {vmod gcrypt error: secure memory not enabled in aes constructor} {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new k = blobcode.blob(HEX, "00000000000000000000000000000000");
new aes = gcrypt.symmetric(AES, ECB, key=k.get(), secure=true);
}
}
varnish v7 -stop
varnish v8 -vcl {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
gcrypt.init(INIT_SECMEM);
gcrypt.init(INIT_SECMEM, 0);
gcrypt.init(FINISH);
new k = blobcode.blob(HEX, "00000000000000000000000000000000");
new aes = gcrypt.symmetric(AES, ECB, key=k.get(), secure=false);
}
} -start
varnish v8 -errvcl {vmod gcrypt error: secure memory not enabled in aes constructor} {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new k = blobcode.blob(HEX, "00000000000000000000000000000000");
new aes = gcrypt.symmetric(AES, ECB, key=k.get(), secure=true);
}
}
varnish v8 -stop
varnish v9 -vcl {
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
gcrypt.init(DISABLE_SECMEM);
gcrypt.init(INIT_SECMEM);
gcrypt.init(FINISH);
new k = blobcode.blob(HEX, "00000000000000000000000000000000");
new aes = gcrypt.symmetric(AES, ECB, key=k.get(), secure=true);
}
} -start
......@@ -73,6 +73,7 @@ struct vmod_gcrypt_symmetric {
};
static const char *gcrypt_version = NULL;
static int secmem_enabled = 1;
static void
errmsg(VRT_CTX, const char *fmt, ...)
......@@ -162,12 +163,62 @@ event(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e e)
"libgcrypt initialization failed");
return 1;
}
/* XXX other initialization */
gcry_control (GCRYCTL_INIT_SECMEM, 65536, 0);
}
return 0;
}
/* Function init */
VCL_VOID
vmod_init(VRT_CTX, VCL_ENUM cmd, VCL_INT n)
{
gcry_error_t err = GPG_ERR_NO_ERROR;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(cmd);
if (ctx->method != VCL_MET_INIT) {
ERR(ctx, "gcrypt.init() is only legal in vcl_init");
return;
}
if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P)) {
VSL(SLT_Debug, 0, "libgcrypt initialization already finished");
return;
}
if (strcmp(cmd, "FINISH") == 0) {
if ((err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED))
!= GPG_ERR_NO_ERROR)
VERR(ctx, "Cannot finish initialization in "
"gcrypt.init(): %s/%s", gcry_strsource(err),
gcry_strerror(err));
return;
}
if (strcmp(cmd, "INIT_SECMEM") == 0) {
if (n < 0) {
VERR(ctx, "INIT_SECMEM number of bytes %d out of range "
"in gcrypt.init()", n);
return;
}
if ((err = gcry_control(GCRYCTL_INIT_SECMEM, n))
!= GPG_ERR_NO_ERROR)
VERR(ctx, "Cannot initialize secure memory to %d bytes "
"in gcrypt.init(): %s/%s", n, gcry_strsource(err),
gcry_strerror(err));
secmem_enabled = n;
return;
}
if (strcmp(cmd, "DISABLE_SECMEM") == 0) {
if ((err = gcry_control(GCRYCTL_DISABLE_SECMEM))
!= GPG_ERR_NO_ERROR)
VERR(ctx, "Cannot disable secure memory in "
"gcrypt.init(): %s/%s", gcry_strsource(err),
gcry_strerror(err));
secmem_enabled = 0;
return;
}
WRONG("Illegal cmd enum");
}
/* Object symmetric */
VCL_VOID
......@@ -191,11 +242,22 @@ vmod_symmetric__init(VRT_CTX, struct vmod_gcrypt_symmetric **symmetricp,
AN(ciphers);
AN(modes);
AN(paddings);
if (!gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P)) {
VERR(ctx,
"libgcrypt initialization not finished in %s constructor",
vcl_name);
return;
}
if (key == NULL || key->priv == NULL) {
VERR(ctx, "key is NULL in %s constructor", vcl_name);
return;
}
assert(key->len >= 0);
if (secure && !secmem_enabled) {
VERR(ctx, "secure memory not enabled in %s constructor",
vcl_name);
return;
}
#define CIPHER(e, m) if (strcmp(ciphers, str(e)) == 0) algo = m;
#include "ciphers.h"
......
......@@ -18,6 +18,8 @@ This Varnish Module (VMOD) provides access to the libgcrypt library of
cryptographic building blocks -- the same library used by the GNU
Privacy Guard cryptographic suite (GnuPG or GPG).
$Function VOID init(ENUM {INIT_SECMEM, DISABLE_SECMEM, FINISH}, INT n=1)
$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",
......
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