Commit 878e804e authored by Geoff Simmons's avatar Geoff Simmons

Separate code for VFP encrypt, decrypt and common.

In anticipation of adding settings and stats.
parent f4ad556f
......@@ -10,8 +10,11 @@ libvmod_ece_la_SOURCES = \
vmod_ece.c \
rfc8188.c \
rfc8188.h \
vfp.c \
vfp.h \
vfp_common.h \
vfp_common.c \
vfp_encrypt.c \
vfp_decrypt.c \
vfp_set_salt.c \
foreign/vend.h \
keys.h \
......@@ -25,7 +28,13 @@ vmod_ece.lo: $(nodist_libvmod_ece_la_SOURCES)
rfc8188.h: foreign/vend.h
vfp.c: rfc8188.h keys.h
vfp_common.h: rfc8188.h vfp.h
vfp_common.c: keys.h
vfp_decrypt.c: vfp_common.h
vfp_encrypt.c: vfp_common.h
vmod_ece.c: vfp.h
......
/*-
* Copyright (c) 2019 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "config.h"
#include "vfp_common.h"
#include "keys.h"
static const char *which[] = { "decrypt", "encrypt" };
enum vfp_status
suck_bytes(struct vfp_ctx *ctx, void *ptr, size_t *lenp)
{
size_t len, off;
ssize_t l;
enum vfp_status vp = VFP_OK;
CHECK_OBJ_NOTNULL(ctx, VFP_CTX_MAGIC);
AN(ptr);
AN(lenp);
len = *lenp;
assert(len > 0);
for (off = 0, l = len; vp == VFP_OK && off < len; l = len - off) {
vp = VFP_Suck(ctx, ptr + off, &l);
assert(l >= 0);
assert(vp >= VFP_ERROR && vp < VFP_NULL);
if (vp == VFP_ERROR)
return (vp);
if (l == 0)
break;
off += l;
assert((unsigned)off <= len);
}
assert(off <= len);
*lenp = off;
return (vp);
}
enum vfp_status
crypto_init(struct vfp_ctx *ctx, struct ece_crypto *crypto, uint8_t *salt,
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];
char errmsg[ERRMSG_LEN];
CHECK_OBJ_NOTNULL(ctx, VFP_CTX_MAGIC);
CHECK_OBJ_NOTNULL(crypto, ECE_CRYPTO_MAGIC);
AN(salt);
AN(id);
AZ(crypto->seq_hi);
AZ(crypto->seq_lo);
KEY_Rdlock(idlen);
key = KEY_Get(id, idlen);
if (key == NULL)
vp = VFP_Error(ctx, "ece %s failure: unknown key %.*s",
which[enc], idlen, id);
else if (derive_prk(salt, key, prk, errmsg) != 0)
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 (VFP_Error(ctx, "ece %s failure: %s", which[enc],
errmsg));
memcpy(crypto->cek, cek, AES128_KEYLEN);
if (derive_prenonce(prk, prenonce, errmsg) != 0)
return (VFP_Error(ctx, "ece %s failure: %s", which[enc],
errmsg));
KEY_Wipe(prk);
KEY_Wipe(prk + AES128_KEYLEN);
crypto->prenonce_hi = vbe32dec(prenonce);
crypto->prenonce_lo = vbe64dec(prenonce + 4);
return (VFP_OK);
}
enum vfp_status
common_alloc(struct vfp_ctx *ctx, struct ece **ecep, int enc)
{
struct ece *ece;
struct ece_crypto *crypto;
struct ece_stream *stream;
struct ece_hdrbuf *hdrbuf;
char errmsg[ERRMSG_LEN];
errno = 0;
ALLOC_OBJ(ece, ECE_MAGIC);
if (ece == NULL)
return (VFP_Error(ctx, "ece %s failure: allocation in init: %s",
which[enc], strerror(errno)));
ece->ectx = cipher_ctx_init(enc, errmsg);
if (ece->ectx == NULL)
return (VFP_Error(ctx, "ece %s failure: "
"initializing cipher context: %s", which[enc],
errmsg));
errno = 0;
ALLOC_OBJ(crypto, ECE_CRYPTO_MAGIC);
if (crypto == NULL)
return (VFP_Error(ctx, "ece %s failure: allocation in init: %s",
which[enc], strerror(errno)));
ALLOC_OBJ(stream, ECE_STREAM_MAGIC);
if (crypto == NULL)
return (VFP_Error(ctx, "ece %s failure: allocation in init: %s",
which[enc], strerror(errno)));
errno = 0;
ALLOC_OBJ(hdrbuf, ECE_HDRBUF_MAGIC);
if (hdrbuf == NULL)
return (VFP_Error(ctx, "ece %s failure: "
"allocation in init: %s",
which[enc], strerror(errno)));
hdrbuf->next_in = hdrbuf->hdr;
hdrbuf->avail_in = HDR_PFX_LEN + MAX_ID_LEN;
ece->crypto = crypto;
ece->stream = stream;
ece->hdr = hdrbuf;
*ecep = ece;
return (VFP_OK);
}
/* VFP .fini method for both encrypt and decrypt */
void v_matchproto_(vfp_fini_f)
vfp_common_fini(struct vfp_ctx *ctx, struct vfp_entry *ent)
{
struct ece *ece;
CHECK_OBJ_NOTNULL(ctx, VFP_CTX_MAGIC);
CHECK_OBJ_NOTNULL(ent, VFP_ENTRY_MAGIC);
if (ent->priv1 == NULL)
return;
CAST_OBJ(ece, ent->priv1, ECE_MAGIC);
if (ece->ectx != NULL)
cipher_ctx_fini(ece->ectx);
if (ece->buf != NULL)
free(ece->buf);
if (ece->crypto != NULL) {
CHECK_OBJ(ece->crypto, ECE_CRYPTO_MAGIC);
KEY_Wipe(ece->crypto->cek);
FREE_OBJ(ece->crypto);
}
if (ece->stream != NULL) {
CHECK_OBJ(ece->stream, ECE_STREAM_MAGIC);
if (ece->stream->rec_buf != NULL)
free(ece->stream->rec_buf);
FREE_OBJ(ece->stream);
}
if (ece->hdr != NULL) {
CHECK_OBJ(ece->hdr, ECE_HDRBUF_MAGIC);
FREE_OBJ(ece->hdr);
}
FREE_OBJ(ece);
}
/*-
* Copyright (c) 2019 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "config.h"
#include "cache/cache.h"
#include <string.h>
#include "rfc8188.h"
#include "vfp.h"
#define HDR_PFX_LEN (SALT_LEN + 4 + 1)
#define MAX_ID_LEN UINT8_MAX
#define MIN_RS 18
#define ERR_VFP(ctx, type, msg) \
VFP_Error((ctx), "ece " type ": " msg)
#define VERR_VFP(ctx, type, fmt, ...) \
VFP_Error((ctx), "ece " type ": " fmt, __VA_ARGS__)
struct ece_stream {
unsigned magic;
#define ECE_STREAM_MAGIC 0x9ea68cef
uint8_t *rec_buf;
uint8_t *rec_next;
uint8_t *next_in;
uint8_t *next_out;
size_t avail_in;
size_t avail_out;
size_t rec_avail;
};
struct ece_hdrbuf {
unsigned magic;
#define ECE_HDRBUF_MAGIC 0xed9a00cf
uint8_t hdr[HDR_PFX_LEN + MAX_ID_LEN];
uint8_t *next_in;
uint16_t avail_in;
};
struct ece_crypto {
unsigned magic;
#define ECE_CRYPTO_MAGIC 0xe7f66e91
unsigned char cek[AES128_KEYLEN];
uint64_t seq_lo;
uint64_t prenonce_lo;
uint32_t seq_hi;
uint32_t prenonce_hi;
};
struct ece {
unsigned magic;
#define ECE_MAGIC 0x2b066cec
struct ece_crypto *crypto;
struct ece_stream *stream;
struct ece_hdrbuf *hdr;
EVP_CIPHER_CTX *ectx;
uint8_t *buf;
size_t chunksz;
uint32_t rs;
};
enum vfp_status suck_bytes(struct vfp_ctx *ctx, void *ptr, size_t *lenp);
enum vfp_status crypto_init(struct vfp_ctx *ctx, struct ece_crypto *crypto,
uint8_t *salt, uint8_t *id, uint8_t idlen, int enc);
enum vfp_status common_alloc(struct vfp_ctx *ctx, struct ece **ecep, int enc);
/* VFP .fini method for both encrypt and decrypt */
void v_matchproto_(vfp_fini_f) vfp_common_fini(struct vfp_ctx *ctx,
struct vfp_entry *ent);
static inline void
setInputBuf(struct ece_stream *stream, void *ptr, ssize_t len)
{
CHECK_OBJ_NOTNULL(stream, ECE_STREAM_MAGIC);
AZ(stream->avail_in);
stream->next_in = ptr;
stream->avail_in = len;
}
static inline int
isInputBufEmpty(struct ece_stream *stream)
{
CHECK_OBJ_NOTNULL(stream, ECE_STREAM_MAGIC);
return (stream->avail_in == 0);
}
static inline enum vfp_status
fillInputBuf(struct vfp_ctx *ctx, struct ece_stream *stream, size_t chunksz,
enum vfp_status vp)
{
size_t len;
enum vfp_status v;
CHECK_OBJ_NOTNULL(stream, ECE_STREAM_MAGIC);
if (stream->avail_in >= chunksz)
return (vp);
len = chunksz - stream->avail_in;
v = suck_bytes(ctx, stream->next_in, &len);
assert(len <= chunksz - stream->avail_in);
stream->next_in += len;
stream->avail_in -= len;
return (v);
}
static inline void
setOutputBuf(struct ece_stream *stream, void *ptr, ssize_t len)
{
CHECK_OBJ_NOTNULL(stream, ECE_STREAM_MAGIC);
stream->next_out = ptr;
stream->avail_out = len;
}
static inline int
isOutputBufFull(struct ece_stream *stream)
{
CHECK_OBJ_NOTNULL(stream, ECE_STREAM_MAGIC);
return (stream->avail_out == 0);
}
static inline void
flushRecBuf(struct ece_stream *stream)
{
size_t len;
CHECK_OBJ_NOTNULL(stream, ECE_STREAM_MAGIC);
if (stream->rec_avail == 0)
return;
len = stream->rec_avail;
if (len > stream->avail_out)
len = stream->avail_out;
memcpy(stream->next_out, stream->rec_next, len);
stream->next_out += len;
stream->avail_out -= len;
stream->rec_next += len;
stream->rec_avail -= len;
}
static inline int
isHdrBufEmpty(struct ece_hdrbuf *hdrbuf)
{
CHECK_OBJ_NOTNULL(hdrbuf, ECE_HDRBUF_MAGIC);
return (hdrbuf->avail_in == 0);
}
static inline void
flushHdrBuf(struct ece_stream *stream, struct ece_hdrbuf *hdrbuf)
{
size_t len;
CHECK_OBJ_NOTNULL(stream, ECE_STREAM_MAGIC);
CHECK_OBJ_NOTNULL(hdrbuf, ECE_HDRBUF_MAGIC);
len = hdrbuf->avail_in;
if (len > stream->avail_out)
len = stream->avail_out;
memcpy(stream->next_out, hdrbuf->next_in, len);
stream->next_out += len;
stream->avail_out -= len;
hdrbuf->next_in += len;
hdrbuf->avail_in -= len;
}
static inline ssize_t
outputLen(struct ece_stream *stream, unsigned char *ptr)
{
CHECK_OBJ_NOTNULL(stream, ECE_STREAM_MAGIC);
assert(stream->next_out >= ptr);
return (stream->next_out - ptr);
}
static inline void
seq_inc(struct ece_crypto *crypto)
{
CHECK_OBJ_NOTNULL(crypto, ECE_CRYPTO_MAGIC);
if (crypto->seq_lo < UINT64_MAX)
crypto->seq_lo++;
else {
assert(crypto->seq_hi != UINT32_MAX);
crypto->seq_hi++;
crypto->seq_lo = 0;
}
}
static inline void
nonce_xor_seq(struct ece_crypto *crypto, uint8_t *nonce)
{
uint32_t nonce_hi;
uint64_t nonce_lo;
CHECK_OBJ_NOTNULL(crypto, ECE_CRYPTO_MAGIC);
AN(nonce);
nonce_hi = crypto->prenonce_hi ^ crypto->seq_hi;
nonce_lo = crypto->prenonce_lo ^ crypto->seq_lo;
vbe32enc(nonce, nonce_hi);
vbe64enc(nonce + 4, nonce_lo);
}
static inline void
common_hdr_set(struct vfp_ctx *ctx)
{
CHECK_OBJ_NOTNULL(ctx, VFP_CTX_MAGIC);
http_Unset(ctx->resp, H_Content_Length);
RFC2616_Weaken_Etag(ctx->resp);
ctx->obj_flags |= OF_CHGCE;
}
This diff is collapsed.
/*-
* Copyright (c) 2019 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "config.h"
#include "vfp_common.h"
#define ERR(ctx, msg) \
ERR_VFP((ctx), "encrypt", msg)
#define VERR(ctx, fmt, ...) \
VERR_VFP((ctx), "encrypt", fmt, __VA_ARGS__)
#define DEFAULT_KEY_HDR "\015X-ECE-Key-ID:"
#define DEFAULT_RS 4096
/*
* Declare the set_salt() function if set-salt was enabled at configure
* time.
*/
#ifdef ENABLE_SET_SALT
enum vfp_status set_salt(struct vfp_ctx *ctx, uint8_t *salt);
#endif
/**
** VFP encrypt
**/
/*
* Return VFP_ERROR on error.
* VFP_NULL if there is insufficient space in the streams for the next
* encrypted record.
* Otherwise the vp status passed in (from suck in the pull method).
*/
static enum vfp_status
encrypt(struct vfp_ctx *ctx, struct ece *ece, enum vfp_status vp)
{
struct ece_stream *stream;
struct ece_crypto *crypto;
size_t record_len, plaintext_len;
ssize_t ciphertext_len;
unsigned char nonce[NONCE_LEN];
char errmsg[ERRMSG_LEN];
int last = (vp == VFP_END);
CHECK_OBJ_NOTNULL(ece, ECE_MAGIC);
CHECK_OBJ_NOTNULL(ece->crypto, ECE_CRYPTO_MAGIC);
CHECK_OBJ_NOTNULL(ece->stream, ECE_STREAM_MAGIC);
stream = ece->stream;
crypto = ece->crypto;
record_len = ece->rs;
if (stream->avail_in < ece->chunksz) {
if (vp != VFP_END)
return (VFP_NULL);
AN(last);
record_len = stream->avail_in + TAG_LEN + 1;
}
assert(record_len <= ece->rs);
if (record_len > stream->avail_out)
return (VFP_NULL);
plaintext_len = record_len - (TAG_LEN + 1);
if (plaintext_len > stream->avail_in)
return (VFP_NULL);
nonce_xor_seq(crypto, nonce);
ciphertext_len = encrypt_record(ece->ectx, stream->next_in,
plaintext_len,
plaintext_len + TAG_LEN + 1,
crypto->cek, nonce, last,
stream->next_out, errmsg);
seq_inc(crypto);
if (ciphertext_len < 0)
return (VERR(ctx, "%s", errmsg));
stream->avail_in -= plaintext_len;
stream->next_in += plaintext_len;
stream->avail_out -= ciphertext_len;
stream->next_out += ciphertext_len;
return (vp);
}
static enum vfp_status v_matchproto_(vfp_init_f)
vfp_encrypt_init(struct vfp_ctx *ctx, struct vfp_entry *ent)
{
struct ece *ece = NULL;
struct ece_hdrbuf *hdrbuf;
const char *keyid;
size_t keyid_len;
char errmsg[ERRMSG_LEN];
CHECK_OBJ_NOTNULL(ctx, VFP_CTX_MAGIC);
CHECK_OBJ_NOTNULL(ent, VFP_ENTRY_MAGIC);
/* XXX implement me */
if (http_GetStatus(ctx->resp) == 206)
return (VFP_NULL);
if (http_GetHdr(ctx->resp, H_Content_Encoding, NULL))
return (VFP_NULL);
/* XXX make the key header configurable */
if (http_GetHdr(ctx->req, DEFAULT_KEY_HDR, &keyid) == 0)
return (VERR(ctx, "key id header %s not found",
DEFAULT_KEY_HDR + 1));
keyid_len = strlen(keyid);
if (keyid_len > MAX_ID_LEN)
return (VERR(ctx, "key id \"%.80s...\" too long "
"(length %zd > 255)", keyid, keyid_len));
if (common_alloc(ctx, &ece, 1) == VFP_ERROR)
return (VFP_ERROR);
CHECK_OBJ_NOTNULL(ece, ECE_MAGIC);
CHECK_OBJ_NOTNULL(ece->stream, ECE_STREAM_MAGIC);
CHECK_OBJ_NOTNULL(ece->crypto, ECE_CRYPTO_MAGIC);
CHECK_OBJ_NOTNULL(ece->hdr, ECE_HDRBUF_MAGIC);
ent->priv1 = ece;
hdrbuf = ece->hdr;
#ifdef ENABLE_SET_SALT
enum vfp_status salt_status;
salt_status = set_salt(ctx, hdrbuf->hdr);
if (salt_status == VFP_ERROR)
return (salt_status);
else if (salt_status == VFP_NULL) {
if (add_salt(hdrbuf->hdr, errmsg) != 0)
return (VERR(ctx, "%s", errmsg));
}
#else
if (add_salt(hdrbuf->hdr, errmsg) != 0)
return (VERR(ctx, "%s", errmsg));
#endif
/* XXX make rs configurable */
ece->rs = DEFAULT_RS;
encode_header(hdrbuf->hdr, ece->rs, (uint8_t)keyid_len,
(uint8_t *)keyid);
if (crypto_init(ctx, ece->crypto, hdrbuf->hdr, (uint8_t *)keyid,
(uint8_t)keyid_len, 1) == VFP_ERROR)
return (VFP_ERROR);
hdrbuf->next_in = hdrbuf->hdr;
hdrbuf->avail_in = HDR_PFX_LEN + keyid_len;
/*
* Allocate space for one input record, but only fetch chunksz,
* such that that there is enough space for the delimiter byte and
* tag. So the input buffer can be safely overwritten with padding
* bytes, delimiter and tag.
*
* XXX allow a configurable max plaintext length per record, which
* must be <= rs - (TAG_LEN + 1) and > 1. The extra bytes are
* padded in each record (so as to obscure the actual size of the
* plaintext message).
*/
errno = 0;
ece->buf = malloc(ece->rs);
if (ece->buf == NULL)
return (VERR(ctx, "buffer allocation failed: %s",
strerror(errno)));
ece->chunksz = ece->rs - (TAG_LEN + 1);
http_SetHeader(ctx->resp, "Content-Encoding: aes128gcm");
RFC2616_Vary_AE(ctx->resp);
common_hdr_set(ctx);
return (VFP_OK);
}
static enum vfp_status v_matchproto_(vfp_pull_f)
vfp_encrypt_pull(struct vfp_ctx *ctx, struct vfp_entry *ent, void *ptr,
ssize_t *lenp)
{
struct ece *ece;
struct ece_stream *stream;
struct ece_hdrbuf *hdrbuf;
unsigned char *p = ptr;
enum vfp_status vp = VFP_OK;
CHECK_OBJ_NOTNULL(ctx, VFP_CTX_MAGIC);
CHECK_OBJ_NOTNULL(ent, VFP_ENTRY_MAGIC);
CAST_OBJ_NOTNULL(ece, ent->priv1, ECE_MAGIC);
CHECK_OBJ_NOTNULL(ece->stream, ECE_STREAM_MAGIC);
CHECK_OBJ_NOTNULL(ece->hdr, ECE_HDRBUF_MAGIC);
AN(ptr);
AN(lenp);
assert(ece->rs > TAG_LEN + 1);
stream = ece->stream;
hdrbuf = ece->hdr;
setOutputBuf(stream, ptr, *lenp);
if (!isHdrBufEmpty(hdrbuf)) {
flushHdrBuf(stream, hdrbuf);
if (isOutputBufFull(stream)) {
*lenp = outputLen(stream, p);
return (VFP_OK);
}
}
while (vp == VFP_OK) {
if (isInputBufEmpty(stream)) {
size_t len = ece->chunksz;
memset(ece->buf, 0, len);
vp = suck_bytes(ctx, ece->buf, &len);
assert(len <= ece->chunksz);
if (vp == VFP_ERROR)
return (vp);
setInputBuf(stream, ece->buf, len);
}
else {
vp = fillInputBuf(ctx, stream, ece->chunksz, vp);
if (vp == VFP_ERROR)
return (vp);
}
if (!isInputBufEmpty(stream)) {
enum vfp_status encrypt_status = encrypt(ctx, ece, vp);
if (encrypt_status == VFP_ERROR)
return (VFP_ERROR);
if (encrypt_status == VFP_NULL) {
/* Output record was buffered */
*lenp = outputLen(stream, p);
return (VFP_OK);
}
}
else if (vp != VFP_END)
ERR(ctx, "message truncated");
}
*lenp = outputLen(stream, p);
return (vp);
}
const struct vfp vfp_encrypt = {
.name = "ece_encrypt",
.init = vfp_encrypt_init,
.pull = vfp_encrypt_pull,
.fini = vfp_common_fini,
};
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