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);
        }
                                                
}