Merge branch 'release/1.3.12-pre3'
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ac156f2..b24b08d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -95,7 +95,7 @@
 
 if (NOT HAVE_SYS_TREE)
     CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/compat/sys/tree.h.in
-			${CMAKE_CURRENT_BINARY_DIR}/compat/sys/tree.h)
+        ${PROJECT_BINARY_DIR}/compat/sys/tree.h)
 
         include_directories(${PROJECT_BINARY_DIR}/compat)
 
@@ -103,7 +103,9 @@
 
 if (NOT HAVE_SYS_QUEUE)
 		CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/compat/sys/queue.h.in
-			${CMAKE_CURRENT_BINARY_DIR}/compat/sys/queue.h)
+            ${PROJECT_BINARY_DIR}/compat/sys/queue.h)
+
+        include_directories(${PROJECT_BINARY_DIR}/compat)
 endif(NOT HAVE_SYS_QUEUE)
 
 if (NOT HAVE_STRNDUP)
diff --git a/ChangeLog b/ChangeLog
index 43be2b6..2484c21 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+v1.3.12-pre3
+ o use PROJECT_BINARY_DIR for sys/ compat headers (012341c Nathan French)
+ o return int for htp__path_new_ (bf59eb1 Nathan French)
+ o more return normalization (91008a6 Nathan French)
+ o allocation functions set *out to NULL (0305c10 Nathan French)
+ o do not return on error from requie_uri (ddc2ce6 Nathan French)
+ o added user-defined custom memory functions (73b54c6 Nathan French)
+ o for some reason, htparser_init was being called manually with type_request?? (a153e5f Nathan French)
+ o Add htp__strndup_ memfn wrapper (763168c Nathan French)
+ o add a callback member in evhtp_ssl_cfg_t for customized decrypt privfile. fixes #16 (b3a4d42 h00360646)
+
 v1.2.12-pre2
  o Internalize some structs / deprecate evhtp_set_hook() (50ab327 Nathan French)
  o remove cruft (1b1a037 Nathan French)
diff --git a/evhtp.c b/evhtp.c
index 37a3cd0..ece5ac8 100644
--- a/evhtp.c
+++ b/evhtp.c
@@ -137,6 +137,111 @@
          (var) = (tvar))
 #endif
 
+#ifndef EVHTP_DISABLE_MEMFUNCTIONS
+
+static void * (*malloc_)(size_t sz) = malloc;
+static void * (* realloc_)(void * d, size_t sz) = realloc;
+static void   (* free_)(void * d) = free;
+
+static void *
+htp__malloc_(size_t size)
+{
+    return malloc_(size);
+}
+
+static void *
+htp__realloc_(void * ptr, size_t size)
+{
+    return realloc_(ptr, size);
+}
+
+static void
+htp__free_(void * ptr)
+{
+    return free_(ptr);
+}
+
+static void *
+htp__calloc_(size_t nmemb, size_t size)
+{
+    if (malloc_ != malloc)
+    {
+        size_t len = nmemb * size;
+        void * p;
+
+        if ((p = malloc_(len)) != NULL)
+        {
+            memset(p, 0, len);
+        }
+
+        return p;
+    }
+
+    return calloc(nmemb, size);
+}
+
+static char *
+htp__strdup_(const char * str)
+{
+    if (malloc_ != malloc)
+    {
+        size_t len = strlen(str);
+        void * p;
+
+        if ((p = malloc_(len + 1)) != NULL)
+        {
+            memcpy(p, str, len + 1);
+        }
+
+        return p;
+    }
+
+    return strdup(str);
+}
+
+static char *
+htp__strndup_(const char * str, size_t len)
+{
+    if (malloc_ != malloc)
+    {
+        char * p;
+
+        if ((p = malloc_(len + 1)) != NULL)
+        {
+            memcpy(p, str, len + 1);
+        }
+
+        p[len] = '\0';
+
+        return p;
+    }
+
+    return strndup(str, len);
+}
+
+#else
+#define htp__malloc_(sz)     malloc(sz)
+#define htp__calloc_(n, sz)  calloc(n, sz)
+#define htp__strdup_(s)      strdup(s)
+#define htp__strndup_(n, sz) strndup(n, sz)
+#define htp__realloc_(p, sz) realloc(p, sz)
+#define htp__free_(p)        free(p)
+#endif
+
+void
+evhtp_set_mem_functions(void *(*mallocfn_)(size_t len),
+                        void *(*reallocfn_)(void * p, size_t sz),
+                        void (* freefn_)(void * p))
+{
+#ifndef EVHTP_DISABLE_MEMFUNCTIONS
+    malloc_  = mallocfn_;
+    realloc_ = reallocfn_;
+    free_    = freefn_;
+
+    return event_set_mem_functions(malloc_, realloc_, free_);
+#endif
+}
+
 static const char *
 status_code_to_str(evhtp_res code)
 {
@@ -279,10 +384,10 @@
 
     if (len < n)
     {
-        return strdup(s);
+        return htp__strdup_(s);
     }
 
-    ret    = malloc(n + 1);
+    ret    = htp__malloc_(n + 1);
     ret[n] = '\0';
 
     memcpy(ret, s, n);
@@ -715,38 +820,42 @@
  * @details if for example the input was "/a/b/c", the parser will
  *          consider "/a/b/" as the path, and "c" as the file.
  *
+ * @param the unallocated destination buffer.
  * @param data raw input data (assumes a /path/[file] structure)
  * @param len length of the input data
  *
- * @return evhtp_request_t * on success, NULL on error.
+ * @return 0 on success, -1 on error.
  */
-static evhtp_path_t *
-htp__path_new_(const char * data, size_t len)
+static int
+htp__path_new_(evhtp_path_t ** out, const char * data, size_t len)
 {
     evhtp_path_t * req_path;
     const char   * data_end = (const char *)(data + len);
     char         * path     = NULL;
     char         * file     = NULL;
 
-    req_path = calloc(sizeof(evhtp_path_t), 1);
+
+    req_path = htp__calloc_(1, sizeof(*req_path));
     evhtp_alloc_assert(req_path);
 
+    *out     = NULL;
+
     if (evhtp_unlikely(len == 0))
     {
         /*
          * odd situation here, no preceding "/", so just assume the path is "/"
          */
-        path = strdup("/");
+        path = htp__strdup_("/");
         evhtp_alloc_assert(path);
     } else if (*data != '/')
     {
         /* request like GET stupid HTTP/1.0, treat stupid as the file, and
          * assume the path is "/"
          */
-        path = strdup("/");
-        file = strndup(data, len);
-
+        path = htp__strdup_("/");
         evhtp_alloc_assert(path);
+
+        file = htp__strndup_(data, len);
         evhtp_alloc_assert(file);
     } else {
         if (data[len - 1] != '/')
@@ -774,23 +883,23 @@
                     /* check for overflow */
                     if ((const char *)(data + path_len) > data_end)
                     {
-                        evhtp_safe_free(req_path, free);
+                        evhtp_safe_free(req_path, htp__free_);
 
-                        return NULL;
+                        return -1;
                     }
 
                     /* check for overflow */
                     if ((const char *)(&data[i + 1] + file_len) > data_end)
                     {
-                        evhtp_safe_free(req_path, free);
+                        evhtp_safe_free(req_path, htp__free_);
 
-                        return NULL;
+                        return -1;
                     }
 
-                    path = strndup(data, path_len);
-                    file = strndup(&data[i + 1], file_len);
-
+                    path = htp__strndup_(data, path_len);
                     evhtp_alloc_assert(path);
+
+                    file = htp__strndup_(&data[i + 1], file_len);
                     evhtp_alloc_assert(file);
 
                     break;
@@ -800,27 +909,27 @@
             if (i == 0 && data[i] == '/' && !file && !path)
             {
                 /* drops here if the request is something like GET /foo */
-                path = strdup("/");
+                path = htp__strdup_("/");
                 evhtp_alloc_assert(path);
 
                 if (len > 1)
                 {
-                    file = strndup((const char *)(data + 1), len);
+                    file = htp__strndup_((const char *)(data + 1), len);
                     evhtp_alloc_assert(file);
                 }
             }
         } else {
             /* the last character is a "/", thus the request is just a path */
-            path = strndup(data, len);
+            path = htp__strndup_(data, len);
             evhtp_alloc_assert(path);
         }
     }
 
     if (len != 0)
     {
-        req_path->full = strndup(data, len);
+        req_path->full = htp__strndup_(data, len);
     } else {
-        req_path->full = strdup("/");
+        req_path->full = htp__strdup_("/");
     }
 
     evhtp_alloc_assert(req_path->full);
@@ -828,7 +937,9 @@
     req_path->path = path;
     req_path->file = file;
 
-    return req_path;
+    *out           = req_path;
+
+    return 0;
 }     /* htp__path_new_ */
 
 static void
@@ -839,31 +950,28 @@
         return;
     }
 
-    evhtp_safe_free(path->full, free);
-    evhtp_safe_free(path->path, free);
-    evhtp_safe_free(path->file, free);
-    evhtp_safe_free(path->match_start, free);
-    evhtp_safe_free(path->match_end, free);
+    evhtp_safe_free(path->full, htp__free_);
+    evhtp_safe_free(path->path, htp__free_);
+    evhtp_safe_free(path->file, htp__free_);
+    evhtp_safe_free(path->match_start, htp__free_);
+    evhtp_safe_free(path->match_end, htp__free_);
 
-    evhtp_safe_free(path, free);
+    evhtp_safe_free(path, htp__free_);
 }
 
 /**
  * @brief create an authority structure
  *
- * @return evhtp_authority_t
+ * @return 0 on success, -1 on error
  */
-static evhtp_authority_t *
-htp__authority_new_(void)
+static int
+htp__authority_new_(evhtp_authority_t ** out)
 {
     evhtp_authority_t * authority;
 
-    if (!(authority = calloc(1, sizeof(*authority))))
-    {
-        return NULL;
-    }
+    *out = htp__calloc_(1, sizeof(*authority));
 
-    return authority;
+    return (*out != NULL) ? 0 : -1;
 }
 
 /**
@@ -879,11 +987,11 @@
         return;
     }
 
-    evhtp_safe_free(authority->username, free);
-    evhtp_safe_free(authority->password, free);
-    evhtp_safe_free(authority->hostname, free);
+    evhtp_safe_free(authority->username, htp__free_);
+    evhtp_safe_free(authority->password, htp__free_);
+    evhtp_safe_free(authority->hostname, htp__free_);
 
-    evhtp_safe_free(authority, free);
+    evhtp_safe_free(authority, htp__free_);
 }
 
 /**
@@ -903,37 +1011,40 @@
     evhtp_safe_free(uri->path, htp__path_free_);
     evhtp_safe_free(uri->authority, htp__authority_free_);
 
-    evhtp_safe_free(uri->fragment, free);
-    evhtp_safe_free(uri->query_raw, free);
+    evhtp_safe_free(uri->fragment, htp__free_);
+    evhtp_safe_free(uri->query_raw, htp__free_);
 
-    evhtp_safe_free(uri, free);
+    evhtp_safe_free(uri, htp__free_);
 }
 
 /**
  * @brief create an overlay URI structure
  *
- * @return evhtp_uri_t
+ * @return 0 on success, -1 on error.
  */
-static evhtp_uri_t *
-htp__uri_new_(void)
+static int
+htp__uri_new_(evhtp_uri_t ** out)
 {
     evhtp_uri_t * uri;
 
-    if (!(uri = calloc(sizeof(evhtp_uri_t), 1)))
+    *out = NULL;
+
+    if ((uri = htp__calloc_(1, sizeof(*uri))) == NULL)
     {
-        return NULL;
+        return -1;
     }
 
-    uri->authority = htp__authority_new_();
+    uri->authority = NULL;
 
-    if (!uri->authority)
+    if (htp__authority_new_(&uri->authority) == -1)
     {
-        htp__uri_free_(uri);
-
-        return NULL;
+        evhtp_safe_free(uri, htp__uri_free_);
+        return -1;
     }
 
-    return uri;
+    *out = uri;
+
+    return 0;
 }
 
 /**
@@ -970,8 +1081,8 @@
         evhtp_safe_free(request->buffer_out, evbuffer_free);
     }
 
-    evhtp_safe_free(request->hooks, free);
-    evhtp_safe_free(request, free);
+    evhtp_safe_free(request->hooks, htp__free_);
+    evhtp_safe_free(request, htp__free_);
 }
 
 /**
@@ -987,7 +1098,7 @@
     evhtp_request_t * req;
     uint8_t           error;
 
-    if (evhtp_unlikely(!(req = calloc(sizeof(evhtp_request_t), 1))))
+    if (evhtp_unlikely(!(req = htp__calloc_(sizeof(evhtp_request_t), 1))))
     {
         return NULL;
     }
@@ -1008,12 +1119,12 @@
             break;
         }
 
-        if (evhtp_unlikely(!(req->headers_in = malloc(sizeof(evhtp_headers_t)))))
+        if (evhtp_unlikely(!(req->headers_in = htp__malloc_(sizeof(evhtp_headers_t)))))
         {
             break;
         }
 
-        if (evhtp_unlikely(!(req->headers_out = malloc(sizeof(evhtp_headers_t)))))
+        if (evhtp_unlikely(!(req->headers_out = htp__malloc_(sizeof(evhtp_headers_t)))))
         {
             break;
         }
@@ -1112,7 +1223,7 @@
             frag_offset           += 1;
             fraglen                = len - frag_offset;
 
-            uri->fragment          = malloc(fraglen + 1);
+            uri->fragment          = htp__malloc_(fraglen + 1);
             evhtp_alloc_assert(uri->fragment);
 
             memcpy(uri->fragment, fragment, fraglen);
@@ -1131,7 +1242,7 @@
         return -1;
     }
 
-    uri->query_raw      = malloc(len + 1);
+    uri->query_raw      = htp__malloc_(len + 1);
     evhtp_alloc_assert(uri->query_raw);
 
     memcpy(uri->query_raw, data, len);
@@ -1160,7 +1271,7 @@
     char               * key_s;
     evhtp_header_t     * hdr;
 
-    key_s      = malloc(len + 1);
+    key_s      = htp__malloc_(len + 1);
     evhtp_alloc_assert(key_s);
 
     key_s[len] = '\0';
@@ -1185,7 +1296,7 @@
     char               * val_s;
     evhtp_header_t     * header;
 
-    val_s      = malloc(len + 1);
+    val_s      = htp__malloc_(len + 1);
     evhtp_alloc_assert(val_s);
 
     val_s[len] = '\0';
@@ -1193,7 +1304,7 @@
 
     if ((header = evhtp_header_val_add(c->request->headers_in, val_s, 0)) == NULL)
     {
-        evhtp_safe_free(val_s, free);
+        evhtp_safe_free(val_s, htp__free_);
         c->request->status = EVHTP_RES_FATAL;
 
         return -1;
@@ -1311,13 +1422,13 @@
 
     if (path->match_start == NULL)
     {
-        path->match_start = calloc(strlen(path->full) + 1, 1);
+        path->match_start = htp__calloc_(strlen(path->full) + 1, 1);
         evhtp_alloc_assert(path->match_start);
     }
 
     if (path->match_end == NULL)
     {
-        path->match_end = calloc(strlen(path->full) + 1, 1);
+        path->match_end = htp__calloc_(strlen(path->full) + 1, 1);
         evhtp_alloc_assert(path->match_end);
     }
 
@@ -1341,7 +1452,7 @@
     {
         if (request->hooks == NULL)
         {
-            request->hooks = malloc(sizeof(evhtp_hooks_t));
+            request->hooks = htp__malloc_(sizeof(evhtp_hooks_t));
             evhtp_alloc_assert(request->hooks);
         }
 
@@ -1414,10 +1525,9 @@
 static int
 htp__require_uri_(evhtp_connection_t * c)
 {
-    if (c && c->request && !c->request->uri)
+    if (c != NULL && c->request != NULL && c->request->uri == NULL)
     {
-        c->request->uri = htp__uri_new_();
-        evhtp_alloc_assert(c->request->uri);
+        evhtp_assert(htp__uri_new_(&c->request->uri) == 0);
     }
 
     return 0;
@@ -1429,15 +1539,15 @@
     evhtp_connection_t * c = htparser_get_userdata(p);
     evhtp_authority_t  * authority;
 
-    if (htp__require_uri_(c) != 0)
+    if (htp__require_uri_(c) == -1)
     {
         return -1;
     }
 
     authority           = c->request->uri->authority;
-    authority->hostname = malloc(len + 1);
+    authority->hostname = htp__malloc_(len + 1);
 
-    if (!authority->hostname)
+    if (authority->hostname == NULL)
     {
         c->request->status = EVHTP_RES_FATAL;
 
@@ -1458,7 +1568,7 @@
     char               * endptr;
     unsigned long        port;
 
-    if (htp__require_uri_(c) != 0)
+    if (htp__require_uri_(c) == -1)
     {
         return -1;
     }
@@ -1484,12 +1594,12 @@
     evhtp_connection_t * c = htparser_get_userdata(p);
     evhtp_path_t       * path;
 
-    if (htp__require_uri_(c) != 0)
+    if (htp__require_uri_(c) == -1)
     {
         return -1;
     }
 
-    if (evhtp_unlikely(!(path = htp__path_new_(data, len))))
+    if (htp__path_new_(&path, data, len) == -1)
     {
         c->request->status = EVHTP_RES_FATAL;
 
@@ -1715,7 +1825,7 @@
         body_len       = evbuffer_get_length(buf_in);
         body           = (const char *)evbuffer_pullup(buf_in, body_len);
 
-        uri->query_raw = calloc(body_len + 1, 1);
+        uri->query_raw = htp__calloc_(body_len + 1, 1);
         evhtp_alloc_assert(uri->query_raw);
 
         memcpy(uri->query_raw, body, body_len);
@@ -2054,7 +2164,7 @@
             c->htp = orig_htp;
         }
 
-        htparser_init(c->parser, htp_type_request);
+        htparser_init(c->parser, c->type);
         htparser_set_userdata(c->parser, c);
 
         return;
@@ -2302,7 +2412,7 @@
             return NULL;
     }
 
-    connection = calloc(sizeof(evhtp_connection_t), 1);
+    connection = htp__calloc_(sizeof(evhtp_connection_t), 1);
     evhtp_alloc_assert(connection);
 
     connection->scratch_buf = evbuffer_new();
@@ -2398,7 +2508,7 @@
 
     htp_log_debug("fd = %d, conn = %p", fd, connection);
 
-    connection->saddr = malloc(sl);
+    connection->saddr = htp__malloc_(sl);
     evhtp_alloc_assert(connection->saddr);
 
     memcpy(connection->saddr, s, sl);
@@ -2694,7 +2804,7 @@
 
     if (valloc == 1)
     {
-        header->val = malloc(header->vlen + 1);
+        header->val = htp__malloc_(header->vlen + 1);
         header->val[header->vlen] = '\0';
         memcpy(header->val, val, header->vlen);
     } else {
@@ -2711,7 +2821,7 @@
 {
     evhtp_kvs_t * kvs;
 
-    kvs = malloc(sizeof(evhtp_kvs_t));
+    kvs = htp__malloc_(sizeof(evhtp_kvs_t));
     evhtp_alloc_assert(kvs);
 
     TAILQ_INIT(kvs);
@@ -2724,7 +2834,7 @@
 {
     evhtp_kv_t * kv;
 
-    kv           = malloc(sizeof(evhtp_kv_t));
+    kv           = htp__malloc_(sizeof(evhtp_kv_t));
     evhtp_alloc_assert(kv);
 
     kv->k_heaped = kalloc;
@@ -2742,9 +2852,9 @@
         {
             char * s;
 
-            if (!(s = malloc(kv->klen + 1)))
+            if (!(s = htp__malloc_(kv->klen + 1)))
             {
-                evhtp_safe_free(kv, free);
+                evhtp_safe_free(kv, htp__free_);
 
                 return NULL;
             }
@@ -2764,7 +2874,7 @@
 
         if (valloc == 1)
         {
-            char * s = malloc(kv->vlen + 1);
+            char * s = htp__malloc_(kv->vlen + 1);
 
             s[kv->vlen] = '\0';
             memcpy(s, val, kv->vlen);
@@ -2787,15 +2897,15 @@
 
     if (kv->k_heaped)
     {
-        evhtp_safe_free(kv->key, free);
+        evhtp_safe_free(kv->key, htp__free_);
     }
 
     if (kv->v_heaped)
     {
-        evhtp_safe_free(kv->val, free);
+        evhtp_safe_free(kv->val, htp__free_);
     }
 
-    evhtp_safe_free(kv, free);
+    evhtp_safe_free(kv, htp__free_);
 }
 
 void
@@ -2834,7 +2944,7 @@
         evhtp_safe_free(kv, evhtp_kv_free);
     }
 
-    evhtp_safe_free(kvs, free);
+    evhtp_safe_free(kvs, htp__free_);
 }
 
 int
@@ -2989,15 +3099,11 @@
     size_t             i;
     enum unscape_state state;
 
-    if (out == NULL || *out == NULL)
-    {
-        return -1;
-    }
-
     state = unscape_state_start;
     optr  = *out;
     sptr  = str;
     d     = 0;
+    *out  = NULL;
 
     for (i = 0; i < str_len; i++)
     {
@@ -3062,7 +3168,7 @@
 }         /* evhtp_unescape_string */
 
 evhtp_query_t *
-evhtp_parse_query_wflags(const char * query, size_t len, int flags)
+evhtp_parse_query_wflags(const char * query, const size_t len, const int flags)
 {
     evhtp_query_t    * query_args;
     query_parser_state state;
@@ -3089,10 +3195,10 @@
     char * key_buf;
     char * val_buf;
 
-    key_buf = malloc(len + 1);
+    key_buf = htp__malloc_(len + 1);
     evhtp_alloc_assert(key_buf);
 
-    val_buf = malloc(len + 1);
+    val_buf = htp__malloc_(len + 1);
     evhtp_alloc_assert(val_buf);
 #endif
 
@@ -3311,15 +3417,15 @@
     }
 
 #ifndef EVHTP_HAS_C99
-    evhtp_safe_free(key_buf, free);
-    evhtp_safe_free(val_buf, free);
+    evhtp_safe_free(key_buf, htp__free_);
+    evhtp_safe_free(val_buf, htp__free_);
 #endif
 
     return query_args;
 error:
 #ifndef EVHTP_HAS_C99
-    evhtp_safe_free(key_buf, free);
-    evhtp_safe_free(val_buf, free);
+    evhtp_safe_free(key_buf, htp__free_);
+    evhtp_safe_free(val_buf, htp__free_);
 #endif
 
     evhtp_query_free(query_args);
@@ -3376,7 +3482,7 @@
     struct evbuffer    * reply_buf;
     struct bufferevent * bev;
 
-    c = evhtp_request_get_connection(request);
+    c = request->conn;
 
     HTP_FLAG_ON(request, EVHTP_REQ_FLAG_FINISHED);
 
@@ -3387,7 +3493,7 @@
         return;
     }
 
-    bev = evhtp_connection_get_bev(c);
+    bev = c->bev;
 
     bufferevent_lock(bev);
     {
@@ -3396,7 +3502,6 @@
     bufferevent_unlock(bev);
 
     evbuffer_drain(reply_buf, -1);
-    /* evbuffer_free(reply_buf); */
 }
 
 int
@@ -3760,7 +3865,7 @@
         evhtp_safe_free(callback, evhtp_callback_free);
     }
 
-    evhtp_safe_free(callbacks, free);
+    evhtp_safe_free(callbacks, htp__free_);
 }
 
 evhtp_callback_t *
@@ -3768,7 +3873,7 @@
 {
     evhtp_callback_t * hcb;
 
-    hcb        = calloc(sizeof(evhtp_callback_t), 1);
+    hcb        = htp__calloc_(sizeof(evhtp_callback_t), 1);
     evhtp_alloc_assert(hcb);
 
     hcb->type  = type;
@@ -3777,26 +3882,26 @@
 
     switch (type) {
         case evhtp_callback_type_hash:
-            hcb->val.path  = strdup(path);
+            hcb->val.path  = htp__strdup_(path);
             break;
 #ifndef EVHTP_DISABLE_REGEX
         case evhtp_callback_type_regex:
-            hcb->val.regex = malloc(sizeof(regex_t));
+            hcb->val.regex = htp__malloc_(sizeof(regex_t));
 
             if (regcomp(hcb->val.regex, (char *)path, REG_EXTENDED) != 0)
             {
-                evhtp_safe_free(hcb->val.regex, free);
-                evhtp_safe_free(hcb, free);
+                evhtp_safe_free(hcb->val.regex, htp__free_);
+                evhtp_safe_free(hcb, htp__free_);
 
                 return NULL;
             }
             break;
 #endif
         case evhtp_callback_type_glob:
-            hcb->val.glob = strdup(path);
+            hcb->val.glob = htp__strdup_(path);
             break;
         default:
-            evhtp_safe_free(hcb, free);
+            evhtp_safe_free(hcb, htp__free_);
 
             return NULL;
     }     /* switch */
@@ -3814,25 +3919,25 @@
 
     switch (callback->type) {
         case evhtp_callback_type_hash:
-            evhtp_safe_free(callback->val.path, free);
+            evhtp_safe_free(callback->val.path, htp__free_);
             break;
         case evhtp_callback_type_glob:
-            evhtp_safe_free(callback->val.glob, free);
+            evhtp_safe_free(callback->val.glob, htp__free_);
             break;
 #ifndef EVHTP_DISABLE_REGEX
         case evhtp_callback_type_regex:
             regfree(callback->val.regex);
-            evhtp_safe_free(callback->val.regex, free);
+            evhtp_safe_free(callback->val.regex, htp__free_);
             break;
 #endif
     }
 
     if (callback->hooks)
     {
-        evhtp_safe_free(callback->hooks, free);
+        evhtp_safe_free(callback->hooks, htp__free_);
     }
 
-    evhtp_safe_free(callback, free);
+    evhtp_safe_free(callback, htp__free_);
 
     return;
 }
@@ -3850,7 +3955,7 @@
 {
     if (*hooks == NULL)
     {
-        if (!(*hooks = calloc(sizeof(evhtp_hooks_t), 1)))
+        if (!(*hooks = htp__calloc_(sizeof(evhtp_hooks_t), 1)))
         {
             return -1;
         }
@@ -4074,7 +4179,7 @@
 
     if (htp->callbacks == NULL)
     {
-        if (!(htp->callbacks = calloc(sizeof(evhtp_callbacks_t), 1)))
+        if (!(htp->callbacks = htp__calloc_(sizeof(evhtp_callbacks_t), 1)))
         {
             htp__unlock_(htp);
 
@@ -4201,7 +4306,7 @@
         return -1;
     }
 
-    if (!(htp->lock = malloc(sizeof(pthread_mutex_t))))
+    if (!(htp->lock = htp__malloc_(sizeof(pthread_mutex_t))))
     {
         return -1;
     }
@@ -4221,7 +4326,7 @@
 
     if (htp->callbacks == NULL)
     {
-        if (!(htp->callbacks = calloc(sizeof(evhtp_callbacks_t), 1)))
+        if (!(htp->callbacks = htp__calloc_(sizeof(evhtp_callbacks_t), 1)))
         {
             htp__unlock_(htp);
 
@@ -4262,7 +4367,7 @@
 
     if (htp->callbacks == NULL)
     {
-        if (!(htp->callbacks = calloc(sizeof(evhtp_callbacks_t), 1)))
+        if (!(htp->callbacks = htp__calloc_(sizeof(evhtp_callbacks_t), 1)))
         {
             htp__unlock_(htp);
 
@@ -4328,8 +4433,8 @@
     ssl_locks_initialized = 1;
     ssl_num_locks         = CRYPTO_num_locks();
 
-    if ((ssl_locks = calloc(ssl_num_locks,
-                            sizeof(evhtp_mutex_t))) == NULL)
+    if ((ssl_locks = htp__calloc_(ssl_num_locks,
+                                  sizeof(evhtp_mutex_t))) == NULL)
     {
         return -1;
     }
@@ -4480,8 +4585,25 @@
     }     /* switch */
 
     SSL_CTX_use_certificate_file(htp->ssl_ctx, cfg->pemfile, SSL_FILETYPE_PEM);
-    SSL_CTX_use_PrivateKey_file(htp->ssl_ctx,
-                                cfg->privfile ? cfg->privfile : cfg->pemfile, SSL_FILETYPE_PEM);
+
+    char * const key = cfg->privfile ?  cfg->privfile : cfg->pemfile;
+
+    if (cfg->decrypt_cb != NULL)
+    {
+        EVP_PKEY * pkey = cfg->decrypt_cb(key);
+
+        if (pkey == NULL)
+        {
+            return -1;
+        }
+
+        SSL_CTX_use_PrivateKey(htp->ssl_ctx, pkey);
+
+        /*cleanup */
+        EVP_PKEY_free(pkey);
+    } else {
+        SSL_CTX_use_PrivateKey_file(htp->ssl_ctx, key, SSL_FILETYPE_PEM);
+    }
 
     SSL_CTX_set_session_id_context(htp->ssl_ctx,
                                    (void *)&session_id_context,
@@ -4635,9 +4757,9 @@
     htp__hook_connection_fini_(connection);
 
     evhtp_safe_free(connection->request, htp__request_free_);
-    evhtp_safe_free(connection->parser, free);
-    evhtp_safe_free(connection->hooks, free);
-    evhtp_safe_free(connection->saddr, free);
+    evhtp_safe_free(connection->parser, htp__free_);
+    evhtp_safe_free(connection->hooks, htp__free_);
+    evhtp_safe_free(connection->saddr, htp__free_);
     evhtp_safe_free(connection->scratch_buf, evbuffer_free);
 
     if (connection->resume_ev)
@@ -4661,7 +4783,7 @@
 #endif
     }
 
-    evhtp_safe_free(connection, free);
+    evhtp_safe_free(connection, htp__free_);
 }     /* evhtp_connection_free */
 
 void
@@ -4756,12 +4878,12 @@
         return -1;
     }
 
-    if (!(alias = calloc(sizeof(evhtp_alias_t), 1)))
+    if (!(alias = htp__calloc_(sizeof(evhtp_alias_t), 1)))
     {
         return -1;
     }
 
-    alias->alias = strdup(name);
+    alias->alias = htp__strdup_(name);
     evhtp_alloc_assert(alias->alias);
 
     TAILQ_INSERT_TAIL(&evhtp->aliases, alias, next);
@@ -4799,7 +4921,7 @@
         return -1;
     }
 
-    if (!(vhost->server_name = strdup(name)))
+    if (!(vhost->server_name = htp__strdup_(name)))
     {
         return -1;
     }
@@ -4829,21 +4951,20 @@
 {
     evhtp_t * htp;
 
-    if (evhtp_unlikely(out == NULL))
-    {
-        return -1;
-    }
 
     if (evhtp_unlikely(evbase == NULL))
     {
         return -1;
     }
 
-    if ((htp = calloc(1, sizeof(evhtp_t))) == NULL)
+    *out = NULL;
+
+    if ((htp = htp__calloc_(1, sizeof(*htp))) == NULL)
     {
         return -1;
     }
 
+
     htp->arg          = arg;
     htp->evbase       = evbase;
     htp->flags        = EVHTP_FLAG_DEFAULTS;
@@ -4907,7 +5028,7 @@
 
     if (evhtp->server_name)
     {
-        evhtp_safe_free(evhtp->server_name, free);
+        evhtp_safe_free(evhtp->server_name, htp__free_);
     }
 
     if (evhtp->callbacks)
@@ -4919,14 +5040,14 @@
     {
         if (evhtp_alias->alias != NULL)
         {
-            evhtp_safe_free(evhtp_alias->alias, free);
+            evhtp_safe_free(evhtp_alias->alias, htp__free_);
         }
 
         TAILQ_REMOVE(&evhtp->aliases, evhtp_alias, next);
-        evhtp_safe_free(evhtp_alias, free);
+        evhtp_safe_free(evhtp_alias, htp__free_);
     }
 
-    evhtp_safe_free(evhtp, free);
+    evhtp_safe_free(evhtp, htp__free_);
 }     /* evhtp_free */
 
 /*****************************************************************
@@ -5101,10 +5222,7 @@
     evbuffer_add_printf(obuf, "%s %s HTTP/%s\r\n",
                         htparser_get_methodstr_m(meth), uri, proto);
 
-    evhtp_headers_for_each(
-        r->headers_out,
-        htp__create_headers_, obuf);
-
+    evhtp_headers_for_each(r->headers_out, htp__create_headers_, obuf);
     evbuffer_add_reference(obuf, "\r\n", 2, NULL, NULL);
 
     if (evbuffer_get_length(r->buffer_out))
diff --git a/evhtp.h b/evhtp.h
index 7bae4e2..835164b 100644
--- a/evhtp.h
+++ b/evhtp.h
@@ -194,6 +194,7 @@
 #ifndef EVHTP_DISABLE_SSL
 typedef int (* evhtp_ssl_verify_cb)(int pre_verify, evhtp_x509_store_ctx_t * ctx);
 typedef int (* evhtp_ssl_chk_issued_cb)(evhtp_x509_store_ctx_t * ctx, evhtp_x509_t * x, evhtp_x509_t * issuer);
+typedef EVP_PKEY * (* evhtp_ssl_decrypt_cb)(char * privfile);
 
 typedef int (* evhtp_ssl_scache_add)(evhtp_connection_t * connection, unsigned char * sid, int sid_len, evhtp_ssl_sess_t * sess);
 typedef void (* evhtp_ssl_scache_del)(evhtp_t * htp, unsigned char * sid, int sid_len);
@@ -201,10 +202,10 @@
 typedef void * (* evhtp_ssl_scache_init)(evhtp_t *);
 #endif
 
-#define EVHTP_VERSION           "1.2.11"
+#define EVHTP_VERSION           "1.2.12-pre3"
 #define EVHTP_VERSION_MAJOR     1
 #define EVHTP_VERSION_MINOR     2
-#define EVHTP_VERSION_PATCH     11
+#define EVHTP_VERSION_PATCH     12
 
 #define evhtp_headers_iterator  evhtp_kvs_iterator
 
@@ -519,6 +520,7 @@
     int                     verify_depth;
     evhtp_ssl_verify_cb     x509_verify_cb;
     evhtp_ssl_chk_issued_cb x509_chk_issued_cb;
+    evhtp_ssl_decrypt_cb    decrypt_cb;
     long                    store_flags;
     evhtp_ssl_scache_type   scache_type;
     long                    scache_timeout;
@@ -531,6 +533,11 @@
 };
 #endif
 
+
+EVHTP_EXPORT void evhtp_set_mem_functions(void *(*malloc_)(size_t),
+    void *(*realloc_)(void *, size_t),
+    void (* free_)(void *));
+
 /**
  * @defgroup evhtp_core Core evhtp functions
  * @{