WiredTiger: WT_ENCRYPTOR Struct Reference

| Version 3.1.0

Fork me on GitHub Join my user group
List of all members | Public Attributes
WT_ENCRYPTOR Struct Reference
WiredTiger Extension API

The interface implemented by applications to provide custom encryption. More...

## Public Attributes
int(* | encrypt )(WT_ENCRYPTOR *encryptor, WT_SESSION *session, uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_len, size_t *result_lenp)
| Callback to encrypt a chunk of data. More...
int(* | decrypt )(WT_ENCRYPTOR *encryptor, WT_SESSION *session, uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_len, size_t *result_lenp)
| Callback to decrypt a chunk of data. More...
int(* | sizing )(WT_ENCRYPTOR *encryptor, WT_SESSION *session, size_t *expansion_constantp)
| Callback to size a destination buffer for encryption. More...
int(* | customize )(WT_ENCRYPTOR *encryptor, WT_SESSION *session, WT_CONFIG_ARG *encrypt_config, WT_ENCRYPTOR **customp)
| If non-NULL, this callback is called to customize the encryptor. More...
int(* | terminate )(WT_ENCRYPTOR *encryptor, WT_SESSION *session)
| If non-NULL, a callback performed when the database is closed. More...

## Detailed Description

The interface implemented by applications to provide custom encryption.

Encryptors must implement the WT_ENCRYPTOR interface: the WT_ENCRYPTOR::encrypt, WT_ENCRYPTOR::decrypt and WT_ENCRYPTOR::sizing callbacks must be specified, WT_ENCRYPTOR::customize and WT_ENCRYPTOR::terminate are optional. To build your own encryptor, use one of the encryptors in `ext/encryptors` as a template: `ext/encryptors/nop_encrypt` is a simple encryptor that passes through data unchanged, and is a reasonable starting point; `ext/encryptors/rotn_encrypt` is an encryptor implementing a simple rotation cipher, it shows the use of `keyid`, `secretkey`, and implements the WT_ENCRYPTOR::customize and WT_ENCRYPTOR::terminate callbacks.

Applications register their implementation with WiredTiger by calling WT_CONNECTION::add_encryptor.

/* Local encryptor structure. */
typedef struct {
WT_ENCRYPTOR encryptor; /* Must come first */
WT_EXTENSION_API *wt_api; /* Extension API */
unsigned long nop_calls; /* Count of calls */
} NOP_ENCRYPTOR;
/*
* wiredtiger_extension_init --
* A simple shared library encryption example.
*/
int
wiredtiger_extension_init(WT_CONNECTION *connection, WT_CONFIG_ARG *config)
{
NOP_ENCRYPTOR *nop_encryptor;
(void)config; /* Unused parameters */
if ((nop_encryptor = calloc(1, sizeof(NOP_ENCRYPTOR))) == NULL)
return (errno);
/*
* Allocate a local encryptor structure, with a WT_ENCRYPTOR structure
* as the first field, allowing us to treat references to either type of
* structure as a reference to the other type.
*
* Heap memory (not static), because it can support multiple databases.
*/
nop_encryptor->encryptor.encrypt = nop_encrypt;
nop_encryptor->encryptor.decrypt = nop_decrypt;
nop_encryptor->encryptor.sizing = nop_sizing;
nop_encryptor->encryptor.terminate = nop_terminate;
nop_encryptor->wt_api = connection->get_extension_api(connection);
/* Load the encryptor */
return (connection->add_encryptor(
connection, "nop", (WT_ENCRYPTOR *)nop_encryptor, NULL));
}

Examples:
  ex_encrypt.c, nop_encrypt.c, and rotn_encrypt.c.

## Member Data Documentation

## ◆ customize

int(* WT_ENCRYPTOR::customize) (WT_ENCRYPTOR *encryptor, WT_SESSION *session, WT_CONFIG_ARG *encrypt_config, WT_ENCRYPTOR **customp)

If non-NULL, this callback is called to customize the encryptor.

The customize function is called whenever a keyid is used for the first time with this encryptor, whether it be in the wiredtiger_open call or the WT_SESSION::create call. This gives the algorithm an opportunity to retrieve and save keys in a customized encryptor. If the callback returns a non-NULL encryptor, that instance is used instead of this one for any callbacks.

Parameters

  [in] | encrypt_config | the "encryption" portion of the configuration from the wiredtiger_open or WT_SESSION::create call
  [out] | customp | the new modified encryptor, or NULL.

Returns
  zero for success, non-zero to indicate an error.

Examples:
  ex_encrypt.c.

## ◆ decrypt

int(* WT_ENCRYPTOR::decrypt) (WT_ENCRYPTOR *encryptor, WT_SESSION *session, uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_len, size_t *result_lenp)

Callback to decrypt a chunk of data.

WT_ENCRYPTOR::decrypt takes a source buffer and a destination buffer. The contents are switched from `encrypt:` the source buffer is the encrypted value, and the destination buffer is sized to be the original size. If the callback successfully decrypts the source buffer to the destination buffer, it returns 0. If an error occurs, it returns an errno or WiredTiger error code.

On entry, `src` will point to memory, with the length of the memory in `src_len`. After successful completion, the callback should return `0` and set `result_lenp` to the number of bytes required for the decrypted representation.

If the `dst` buffer is not big enough to hold the decrypted data, the callback should return an error.

This callback cannot be NULL.

Parameters

  [in] | src | the data to decrypt
  [in] | src_len | the length of the data to decrypt
  [in] | dst | the destination buffer
  [in] | dst_len | the length of the destination buffer
  [out] | result_lenp | the length of the decrypted data

Returns
  zero for success, non-zero to indicate an error.

/*
* nop_decrypt --
* A simple decryption example that passes data through unchanged.
*/
static int
nop_decrypt(WT_ENCRYPTOR *encryptor, WT_SESSION *session,
uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_len,
size_t *result_lenp)
{
NOP_ENCRYPTOR *nop_encryptor = (NOP_ENCRYPTOR *)encryptor;
(void)session; /* Unused parameters */
(void)src_len;
++nop_encryptor->nop_calls; /* Call count */
/*
* The destination length is the number of unencrypted bytes we're
* expected to return.
*/
memcpy(dst, src, dst_len);
*result_lenp = dst_len;
return (0);
}

Examples:
  ex_encrypt.c.

## ◆ encrypt

int(* WT_ENCRYPTOR::encrypt) (WT_ENCRYPTOR *encryptor, WT_SESSION *session, uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_len, size_t *result_lenp)

Callback to encrypt a chunk of data.

WT_ENCRYPTOR::encrypt takes a source buffer and a destination buffer. The callback encrypts the source buffer (plain text) into the destination buffer.

On entry, `src` will point to memory, with the length of the memory in `src_len`. After successful completion, the callback should return `0` and set `result_lenp` to the number of bytes required for the encrypted representation.

On entry, `dst` points to the destination buffer with a length of `dst_len`. The destination buffer will be at least src_len plus the size returned by that WT_ENCRYPT::sizing.

This callback cannot be NULL.

Parameters

  [in] | src | the data to encrypt
  [in] | src_len | the length of the data to encrypt
  [in] | dst | the destination buffer
  [in] | dst_len | the length of the destination buffer
  [out] | result_lenp | the length of the encrypted data

Returns
  zero for success, non-zero to indicate an error.

/*
* nop_encrypt --
* A simple encryption example that passes data through unchanged.
*/
static int
nop_encrypt(WT_ENCRYPTOR *encryptor, WT_SESSION *session,
uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_len,
size_t *result_lenp)
{
NOP_ENCRYPTOR *nop_encryptor = (NOP_ENCRYPTOR *)encryptor;
(void)session; /* Unused parameters */
++nop_encryptor->nop_calls; /* Call count */
if (dst_len < src_len)
return (nop_error(nop_encryptor, session,
ENOMEM, "encrypt buffer not big enough"));
memcpy(dst, src, src_len);
*result_lenp = src_len;
return (0);
}

Examples:
  ex_encrypt.c.

## ◆ sizing

int(* WT_ENCRYPTOR::sizing) (WT_ENCRYPTOR *encryptor, WT_SESSION *session, size_t *expansion_constantp)

Callback to size a destination buffer for encryption.

WT_ENCRYPTOR::sizing is an callback that returns the number of additional bytes that is needed when encrypting a text buffer. This is always necessary, since encryptors typically generate encrypted text that is larger than the plain text input. Without such a call, WiredTiger would have no way to know the worst case for the encrypted buffer size. The WiredTiger encryption infrastructure assumes that buffer sizing is not dependent on the number of bytes of input, that there is a one to one relationship in number of bytes needed between input and output.

This callback cannot be NULL.

The callback should set `expansion_constantp` to the additional number of bytes needed.

Parameters

  [out] | expansion_constantp | the additional number of bytes needed when encrypting.

Returns
  zero for success, non-zero to indicate an error.

/*
* nop_sizing --
* A simple sizing example that tells wiredtiger that the
* encrypted buffer is always the same as the source buffer.
*/
static int
nop_sizing(WT_ENCRYPTOR *encryptor, WT_SESSION *session,
size_t *expansion_constantp)
{
NOP_ENCRYPTOR *nop_encryptor = (NOP_ENCRYPTOR *)encryptor;
(void)session; /* Unused parameters */
++nop_encryptor->nop_calls; /* Call count */
*expansion_constantp = 0;
return (0);
}

Examples:
  ex_encrypt.c.

## ◆ terminate

int(* WT_ENCRYPTOR::terminate) (WT_ENCRYPTOR *encryptor, WT_SESSION *session)

If non-NULL, a callback performed when the database is closed.

It is called for each encryptor that was added using WT_CONNECTION::add_encryptor or returned by the WT_ENCRYPTOR::customize callback.

The WT_ENCRYPTOR::terminate callback is intended to allow cleanup, the handle will not be subsequently accessed by WiredTiger.

/*
* nop_terminate --
* WiredTiger no-op encryption termination.
*/
static int
nop_terminate(WT_ENCRYPTOR *encryptor, WT_SESSION *session)
{
NOP_ENCRYPTOR *nop_encryptor = (NOP_ENCRYPTOR *)encryptor;
(void)session; /* Unused parameters */
++nop_encryptor->nop_calls; /* Call count */
/* Free the allocated memory. */
free(encryptor);
return (0);
}

Examples:
  ex_encrypt.c.