return 0;
}
-/* cheats - internal OpenSSL 1.1 structures */
-typedef struct evp_cipher_ctx_st {
+/* cheats - internal OpenSSL 1.1 structures
+ * These are copied from the OpenSSL source code.
+ *
+ * We use these to allow stack allocation of these structures
+ * and to prevent OpenSSL from malloc'ing and free'ing them,
+ * which would be too slow.
+ */
+typedef struct my_cipher_ctx_st {
const EVP_CIPHER *cipher;
ENGINE *engine; /* functional reference if 'cipher' is
* ENGINE-provided */
void *algctx;
EVP_CIPHER *fetched_cipher;
#endif
-} EVP_CIPHER_CTX;
+} MY_CIPHER_CTX;
+
+typedef struct evp_cipher_head {
+ int nid;
+ int block_size;
+ int key_len;
+ int iv_len;
+ unsigned long flags;
+ int (*init)(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc);
+} evp_cipher_head;
#define CHACHA_KEY_SIZE 32
#define CHACHA_CTR_SIZE 16
unsigned int counter[CHACHA_CTR_SIZE / 4];
unsigned char buf[CHACHA_BLK_SIZE];
unsigned int partial_len;
-} EVP_CHACHA_KEY;
+} MY_CHACHA_KEY;
typedef struct {
- EVP_CHACHA_KEY key;
+ MY_CHACHA_KEY key;
unsigned int nonce[12/4];
unsigned char tag[POLY1305_BLOCK_SIZE];
unsigned char tls_aad[POLY1305_BLOCK_SIZE];
struct { uint64_t aad, text; } len;
int aad, mac_inited, tag_len, nonce_len;
size_t tls_payload_length;
-} EVP_CHACHA_AEAD_CTX;
+} MY_CHACHA_AEAD_CTX;
+
+typedef struct {
+ double opaque[24];
+ unsigned int nonce[4];
+ unsigned char data[POLY1305_BLOCK_SIZE];
+ size_t num;
+ struct {
+ void (*foo1)();
+ void (*foo2)();
+ } func;
+} my_poly1305_ctx;
+
+typedef struct my_cipherdata {
+ MY_CHACHA_AEAD_CTX aead_ctx;
+ my_poly1305_ctx poly_ctx;
+} my_cipherdata;
static int mcf_encfunc(const MDB_val *src, MDB_val *dst, const MDB_val *key, int encdec)
{
unsigned char iv[12];
int ivl, outl, rc;
mdb_size_t *ptr;
- EVP_CIPHER_CTX ctx = {0};
- EVP_CHACHA_AEAD_CTX cactx;
+ MY_CIPHER_CTX myctx = {0};
+ EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX *)&myctx;
+ my_cipherdata cactx;
+ evp_cipher_head *eh = (evp_cipher_head *)cipher;
- ctx.cipher_data = &cactx;
ptr = key[1].mv_data;
ivl = ptr[0] & 0xffffffff;
memcpy(iv, &ivl, 4);
memcpy(iv+4, ptr+1, sizeof(mdb_size_t));
- EVP_CipherInit_ex(&ctx, cipher, NULL, key[0].mv_data, iv, encdec);
- EVP_CIPHER_CTX_set_padding(&ctx, 0);
+ EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, encdec);
+
+ /* we can't set cipher_data before calling CipherInit because
+ * that will just try to free it. So set it now, and then finish
+ * up the other two Init calls that we disabled before.
+ */
+ myctx.cipher_data = &cactx;
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL);
+ eh->init(ctx, key[0].mv_data, iv, encdec);
+
+ EVP_CIPHER_CTX_set_padding(ctx, 0);
if (!encdec) {
- EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_AEAD_SET_TAG, key[2].mv_size, key[2].mv_data);
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, key[2].mv_size, key[2].mv_data);
}
- rc = EVP_CipherUpdate(&ctx, dst->mv_data, &outl, src->mv_data, src->mv_size);
+ rc = EVP_CipherUpdate(ctx, dst->mv_data, &outl, src->mv_data, src->mv_size);
if (rc)
- rc = EVP_CipherFinal_ex(&ctx, key[2].mv_data, &outl);
+ rc = EVP_CipherFinal_ex(ctx, key[2].mv_data, &outl);
if (rc && encdec) {
- EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_AEAD_GET_TAG, key[2].mv_size, key[2].mv_data);
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, key[2].mv_size, key[2].mv_data);
}
return rc == 0;
}
MDB_crypto_funcs *MDB_crypto()
{
+ evp_cipher_head *eh;
cipher = (EVP_CIPHER *)EVP_chacha20_poly1305();
+
+ /* We must disable the implicit init calls */
+ eh = (evp_cipher_head *)cipher;
+ eh->flags &= ~(EVP_CIPH_CTRL_INIT|EVP_CIPH_ALWAYS_CALL_INIT);
+
return (MDB_crypto_funcs *)&mcf_table;
}