Commit 7d8800eb authored by Geoff Simmons's avatar Geoff Simmons

Add delete_key().

Led to some bugfixing in the VFP code (generating proper error
messages).
parent 45ec1b7b
......@@ -412,3 +412,43 @@ KEY_Set(VRT_CTX, uint8_t *id, uint8_t idlen, const uint8_t *key)
KEY_Unlock(idlen);
return (-1);
}
int
KEY_Delete(VRT_CTX, uint8_t *id, uint8_t idlen)
{
struct key_tree *tree_h;
struct key *k;
struct addr_ent *addr_ent;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(id);
key_wrlock(idlen);
tree_h = &key_tbl[idlen].tree;
k = key_find(tree_h, id, idlen);
if (k == NULL) {
VRT_fail(ctx, "key \"%.*s\" not found", idlen, id);
KEY_Unlock(idlen);
return (-1);
}
CHECK_OBJ(k, KEY_MAGIC);
VRBT_REMOVE(key_tree, tree_h, k);
KEY_Unlock(idlen);
KEY_Wipe(k->key);
errno = 0;
ALLOC_OBJ(addr_ent, ADDR_ENTRY_MAGIC);
if (addr_ent == NULL) {
VRT_fail(ctx, "allocating address entry: %s", vstrerror(errno));
return (-1);
}
addr_ent->addr = k->key;
FREE_OBJ(k);
Lck_Lock(&page_mtx);
VSTAILQ_INSERT_TAIL(&addr_head, addr_ent, list);
Lck_Unlock(&page_mtx);
return (0);
}
......@@ -39,3 +39,4 @@ void KEY_Unlock(uint8_t idlen);
uint8_t *KEY_Get(uint8_t *id, uint8_t idlen);
int KEY_Set(VRT_CTX, uint8_t *id, uint8_t idlen, const uint8_t *key);
void KEY_Wipe(void * const key);
int KEY_Delete(VRT_CTX, uint8_t *id, uint8_t idlen);
# looks like -*- vcl -*-
varnishtest "key manipulation functions"
server s1 {
rxreq
txresp -body {encrypt me}
} -start
varnish v1 -vcl+backend {
import ${vmod_ece};
import blob;
sub vcl_init {
ece.set_key("delete me", blob.decode(BASE64,
encoded="paFlLDjHC3rnUp4hOmph+g=="));
}
sub vcl_backend_response {
ece.delete_key("delete me");
set bereq.http.X-ECE-Key-ID = "delete me";
set beresp.filters = "ece_encrypt";
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 503
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "FetchError" {
expect 0 * Begin bereq
expect * = FetchError {^ece encrypt failure: unknown key delete me$}
expect * = End
} -run
varnish v1 -errvcl {key "no such key" not found} {
import ${vmod_ece};
backend b { .host="${bad_ip}"; }
sub vcl_init {
ece.delete_key("no such key");
}
}
varnish v1 -errvcl {too long} {
import ${vmod_ece};
backend b { .host="${bad_ip}"; }
sub vcl_init {
ece.delete_key({"
1234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890
"});
}
}
varnish v1 -vcl {
import ${vmod_ece};
backend b { .host="${bad_ip}"; }
sub vcl_recv {
ece.delete_key(req.http.No-Such-Header);
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^key id is NULL$}
expect * = End
} -start
client c1 {
txreq
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
} -run
logexpect l1 -wait
......@@ -106,6 +106,8 @@ struct ece {
uint32_t rs;
};
static const char *which[] = { "decrypt", "encrypt" };
/*
* Declare the set_salt() function if set-salt was enabled at configure
* time.
......@@ -245,7 +247,7 @@ fillInputBuf(struct vfp_ctx *ctx, struct ece_stream *stream, size_t chunksz,
static enum vfp_status
crypto_init(struct vfp_ctx *ctx, struct ece_crypto *crypto, uint8_t *salt,
uint8_t *id, uint8_t idlen)
uint8_t *id, uint8_t idlen, int enc)
{
enum vfp_status vp = VFP_OK;
uint8_t *key, prk[SHA256_LEN], cek[SHA256_LEN], prenonce[NONCE_LEN];
......@@ -261,18 +263,21 @@ crypto_init(struct vfp_ctx *ctx, struct ece_crypto *crypto, uint8_t *salt,
KEY_Rdlock(idlen);
key = KEY_Get(id, idlen);
if (key == NULL)
vp = VERR_DEC(ctx, "unknown key %.*s", idlen, id);
vp = VFP_Error(ctx, "ece %s failure: unknown key %.*s",
which[enc], idlen, id);
else if (derive_prk(salt, key, prk, errmsg) != 0)
vp = VERR_DEC(ctx, "%s", errmsg);
vp = VFP_Error(ctx, "ece %s failure: %s", which[enc], errmsg);
KEY_Unlock(idlen);
if (vp == VFP_ERROR)
return (vp);
if (derive_cek(prk, cek, errmsg) != 0)
return (VERR_DEC(ctx, "%s", errmsg));
return (VFP_Error(ctx, "ece %s failure: %s", which[enc],
errmsg));
memcpy(crypto->cek, cek, AES128_KEYLEN);
if (derive_prenonce(prk, prenonce, errmsg) != 0)
return (VERR_DEC(ctx, "%s", errmsg));
return (VFP_Error(ctx, "ece %s failure: %s", which[enc],
errmsg));
KEY_Wipe(prk);
KEY_Wipe(prk + AES128_KEYLEN);
......@@ -328,7 +333,6 @@ common_alloc(struct vfp_ctx *ctx, struct ece **ecep, int enc)
struct ece_crypto *crypto;
struct ece_stream *stream;
struct ece_hdrbuf *hdrbuf;
const char *which[] = { "decrypt", "encrypt" };
char errmsg[ERRMSG_LEN];
errno = 0;
......@@ -486,7 +490,7 @@ decrypt_init(struct vfp_ctx *ctx, struct ece *ece)
ece->rs, INT_MAX));
if (crypto_init(ctx, ece->crypto, hdr->hdr, hdr->hdr + HDR_PFX_LEN,
idlen) == VFP_ERROR)
idlen, 0) == VFP_ERROR)
return (VFP_ERROR);
/* set chunksz so that the fetches fit rs */
......@@ -812,7 +816,7 @@ vfp_encrypt_init(struct vfp_ctx *ctx, struct vfp_entry *ent)
(uint8_t *)keyid);
if (crypto_init(ctx, ece->crypto, hdrbuf->hdr, (uint8_t *)keyid,
(uint8_t)keyid_len) == VFP_ERROR)
(uint8_t)keyid_len, 1) == VFP_ERROR)
return (VFP_ERROR);
hdrbuf->next_in = hdrbuf->hdr;
hdrbuf->avail_in = HDR_PFX_LEN + keyid_len;
......
......@@ -101,6 +101,28 @@ vmod_set_key(VRT_CTX, VCL_STRING id, VCL_BLOB key)
(void)KEY_Set(ctx, (uint8_t *)id, (uint8_t)len, key->blob);
}
VCL_VOID
vmod_delete_key(VRT_CTX, VCL_STRING id)
{
size_t len;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
if (id == NULL) {
VRT_fail(ctx, "key id is NULL");
return;
}
len = strlen(id);
if (len > 255) {
VRT_fail(ctx, "key id \"%s\" too long (length %zu > 255)", id,
len);
return;
}
/* KEY_Delete calls VRT_fail() on error. */
(void)KEY_Delete(ctx, (uint8_t *)id, (uint8_t)len);
}
VCL_STRING
vmod_libcrypto_version(VRT_CTX)
{
......
......@@ -63,6 +63,12 @@ blob ``key``.
XXX ...
$Function VOID delete_key(STRING id)
Remove the keying material identified by ``id``.
XXX ...
$Function STRING libcrypto_version()
Return the libcrypto version string.
......
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