Shows a simple encryptor as a plug in library.
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <wiredtiger.h>
#include <wiredtiger_ext.h>
typedef struct {
int rot_N;
char *keyid;
char *secretkey;
u_char *shift_forw;
u_char *shift_back;
size_t shift_len;
bool force_error;
} ROTN_ENCRYPTOR;
#define CHKSUM_LEN 4
#define IV_LEN 16
static int
rotn_error(
ROTN_ENCRYPTOR *encryptor,
WT_SESSION *session,
int err,
const char *msg)
{
wt_api = encryptor->wt_api;
"rotn encryption: %s: %s",
msg, wt_api->
strerror(wt_api, NULL, err));
return (err);
}
static void
make_checksum(uint8_t *dst)
{
int i;
for (i = 0; i < CHKSUM_LEN; i++)
dst[i] = 'C';
}
static void
make_iv(uint8_t *dst)
{
int i;
for (i = 0; i < IV_LEN; i++)
dst[i] = 'I';
}
static void
do_rotate(char *buf, size_t len, int rotn)
{
uint32_t i;
for (i = 0; i < len; i++) {
if ('a' <= buf[i] && buf[i] <= 'z')
buf[i] = ((buf[i] - 'a') + rotn) % 26 + 'a';
else if ('A' <= buf[i] && buf[i] <= 'Z')
buf[i] = ((buf[i] - 'A') + rotn) % 26 + 'A';
}
}
static void
do_shift(uint8_t *buf, size_t len, u_char *shift, size_t shiftlen)
{
uint32_t i;
for (i = 0; i < len; i++)
buf[i] += shift[i % shiftlen];
}
static int
uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_len,
size_t *result_lenp)
{
ROTN_ENCRYPTOR *rotn_encryptor = (ROTN_ENCRYPTOR *)encryptor;
uint32_t i;
(void)session;
if (dst_len < src_len + CHKSUM_LEN + IV_LEN)
return (rotn_error(rotn_encryptor, session,
ENOMEM, "encrypt buffer not big enough"));
i = CHKSUM_LEN + IV_LEN;
memcpy(&dst[i], &src[0], src_len);
if (rotn_encryptor->shift_len == 0)
do_rotate((char *)dst + i, src_len, rotn_encryptor->rot_N);
else
do_shift(&dst[i], src_len,
rotn_encryptor->shift_forw, rotn_encryptor->shift_len);
i = 0;
make_checksum(&dst[i]);
i += CHKSUM_LEN;
make_iv(&dst[i]);
*result_lenp = dst_len;
return (0);
}
static int
uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_len,
size_t *result_lenp)
{
ROTN_ENCRYPTOR *rotn_encryptor = (ROTN_ENCRYPTOR *)encryptor;
size_t mylen;
uint32_t i;
(void)session;
if (rotn_encryptor->force_error)
return (-1000);
mylen = src_len - (CHKSUM_LEN + IV_LEN);
if (dst_len < mylen)
return (rotn_error(rotn_encryptor, session,
ENOMEM, "decrypt buffer not big enough"));
i = CHKSUM_LEN + IV_LEN;
memcpy(&dst[0], &src[i], mylen);
if (rotn_encryptor->shift_len == 0)
do_rotate((char *)dst, mylen, 26 - rotn_encryptor->rot_N);
else
do_shift(&dst[0], mylen,
rotn_encryptor->shift_back, rotn_encryptor->shift_len);
*result_lenp = mylen;
return (0);
}
static int
size_t *expansion_constantp)
{
(void)encryptor;
(void)session;
*expansion_constantp = CHKSUM_LEN + IV_LEN;
return (0);
}
static int
{
const ROTN_ENCRYPTOR *orig;
ROTN_ENCRYPTOR *rotn_encryptor;
size_t i, len;
int ret, keyid_val;
u_char base;
ret = 0;
keyid_val = 0;
orig = (const ROTN_ENCRYPTOR *)encryptor;
wt_api = orig->wt_api;
if ((rotn_encryptor = calloc(1, sizeof(ROTN_ENCRYPTOR))) == NULL)
return (errno);
*rotn_encryptor = *orig;
rotn_encryptor->keyid = rotn_encryptor->secretkey = NULL;
if ((ret = wt_api->
config_get(wt_api, session, encrypt_config,
"keyid", &keyid)) == 0 && keyid.
len != 0) {
if ((keyid_val = atoi(keyid.
str)) < 0) {
ret = rotn_error(rotn_encryptor,
NULL, EINVAL, "rotn_customize: invalid keyid");
goto err;
}
if ((rotn_encryptor->keyid = malloc(keyid.
len + 1)) == NULL) {
ret = errno;
goto err;
}
strncpy(rotn_encryptor->keyid, keyid.
str, keyid.
len + 1);
rotn_encryptor->keyid[keyid.
len] =
'\0';
}
if ((ret = wt_api->
config_get(wt_api, session, encrypt_config,
"secretkey", &secret)) == 0 && secret.
len != 0) {
if ((rotn_encryptor->secretkey = malloc(len + 1)) == NULL ||
(rotn_encryptor->shift_forw = malloc(len)) == NULL ||
(rotn_encryptor->shift_back = malloc(len)) == NULL) {
ret = errno;
goto err;
}
for (i = 0; i < len; i++) {
if (
'a' <= secret.
str[i] && secret.
str[i] <=
'z')
base = 'a';
else if (
'A' <= secret.
str[i] && secret.
str[i] <=
'Z')
base = 'A';
else {
ret = rotn_error(rotn_encryptor, NULL,
EINVAL, "rotn_customize: invalid key");
goto err;
}
base -= (u_char)keyid_val;
rotn_encryptor->shift_forw[i] =
(u_char)secret.
str[i] - base;
rotn_encryptor->shift_back[i] =
base - (u_char)secret.
str[i];
}
rotn_encryptor->shift_len = len;
strncpy(rotn_encryptor->secretkey, secret.
str, secret.
len + 1);
rotn_encryptor->secretkey[secret.
len] =
'\0';
}
rotn_encryptor->rot_N = keyid_val;
return (0);
err: free(rotn_encryptor->keyid);
free(rotn_encryptor->secretkey);
free(rotn_encryptor->shift_forw);
free(rotn_encryptor->shift_back);
free(rotn_encryptor);
return (ret);
}
static int
{
ROTN_ENCRYPTOR *rotn_encryptor = (ROTN_ENCRYPTOR *)encryptor;
(void)session;
free(rotn_encryptor->secretkey);
free(rotn_encryptor->keyid);
free(rotn_encryptor->shift_forw);
free(rotn_encryptor->shift_back);
free(encryptor);
return (0);
}
static int
rotn_configure(ROTN_ENCRYPTOR *rotn_encryptor,
WT_CONFIG_ARG *config)
{
int ret;
wt_api = rotn_encryptor->wt_api;
wt_api, NULL, config, "rotn_force_error", &v)) == 0)
rotn_encryptor->force_error = v.
val != 0;
return (rotn_error(rotn_encryptor, NULL, EINVAL,
"error parsing config"));
return (0);
}
int
{
ROTN_ENCRYPTOR *rotn_encryptor;
int ret;
if ((rotn_encryptor = calloc(1, sizeof(ROTN_ENCRYPTOR))) == NULL)
return (errno);
rotn_encryptor->encryptor.encrypt = rotn_encrypt;
rotn_encryptor->encryptor.decrypt = rotn_decrypt;
rotn_encryptor->encryptor.sizing = rotn_sizing;
rotn_encryptor->encryptor.customize = rotn_customize;
rotn_encryptor->encryptor.terminate = rotn_terminate;
if ((ret = rotn_configure(rotn_encryptor, config)) != 0) {
free(rotn_encryptor);
return (ret);
}
connection,
"rotn", (
WT_ENCRYPTOR *)rotn_encryptor, NULL)) == 0)
return (0);
free(rotn_encryptor);
return (ret);
}