summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 06:30:05 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 06:30:05 +0000
commita1e354165254cd9e346751e6c2ddc554feeb0e6d (patch)
tree5fd273cc604fd00efd630eb387a6f79ce102f4e3 /crypto
parentInitial commit. (diff)
downloadapr-util-a1e354165254cd9e346751e6c2ddc554feeb0e6d.tar.xz
apr-util-a1e354165254cd9e346751e6c2ddc554feeb0e6d.zip
Adding upstream version 1.6.3.upstream/1.6.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/apr_crypto.c608
-rw-r--r--crypto/apr_crypto_commoncrypto.c906
-rw-r--r--crypto/apr_crypto_nss.c1097
-rw-r--r--crypto/apr_crypto_nss.dep15
-rw-r--r--crypto/apr_crypto_nss.dsp203
-rw-r--r--crypto/apr_crypto_nss.mak594
-rw-r--r--crypto/apr_crypto_openssl.c973
-rw-r--r--crypto/apr_crypto_openssl.dep14
-rw-r--r--crypto/apr_crypto_openssl.dsp203
-rw-r--r--crypto/apr_crypto_openssl.mak606
-rw-r--r--crypto/apr_md4.c409
-rw-r--r--crypto/apr_md5.c666
-rw-r--r--crypto/apr_passwd.c200
-rw-r--r--crypto/apr_sha1.c368
-rw-r--r--crypto/apr_siphash.c196
-rw-r--r--crypto/crypt_blowfish.c902
-rw-r--r--crypto/crypt_blowfish.h27
-rw-r--r--crypto/getuuid.c208
-rw-r--r--crypto/uuid.c130
19 files changed, 8325 insertions, 0 deletions
diff --git a/crypto/apr_crypto.c b/crypto/apr_crypto.c
new file mode 100644
index 0000000..9ba190e
--- /dev/null
+++ b/crypto/apr_crypto.c
@@ -0,0 +1,608 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+
+#include "apu_config.h"
+#include "apu.h"
+#include "apr_pools.h"
+#include "apr_dso.h"
+#include "apr_strings.h"
+#include "apr_hash.h"
+#include "apr_thread_mutex.h"
+#include "apr_lib.h"
+
+#if APU_HAVE_CRYPTO
+
+#include "apu_internal.h"
+#include "apr_crypto_internal.h"
+#include "apr_crypto.h"
+#include "apu_version.h"
+
+static apr_hash_t *drivers = NULL;
+
+#define ERROR_SIZE 1024
+
+#define CLEANUP_CAST (apr_status_t (*)(void*))
+
+#define APR_TYPEDEF_STRUCT(type, incompletion) \
+struct type { \
+ incompletion \
+ void *unk[]; \
+};
+
+APR_TYPEDEF_STRUCT(apr_crypto_t,
+ apr_pool_t *pool;
+ apr_crypto_driver_t *provider;
+)
+
+APR_TYPEDEF_STRUCT(apr_crypto_key_t,
+ apr_pool_t *pool;
+ apr_crypto_driver_t *provider;
+ const apr_crypto_t *f;
+)
+
+APR_TYPEDEF_STRUCT(apr_crypto_block_t,
+ apr_pool_t *pool;
+ apr_crypto_driver_t *provider;
+ const apr_crypto_t *f;
+)
+
+typedef struct apr_crypto_clear_t {
+ void *buffer;
+ apr_size_t size;
+} apr_crypto_clear_t;
+
+#if !APU_DSO_BUILD
+#define DRIVER_LOAD(name,driver_name,pool,params,rv,result) \
+ { \
+ extern const apr_crypto_driver_t driver_name; \
+ apr_hash_set(drivers,name,APR_HASH_KEY_STRING,&driver_name); \
+ if (driver_name.init) { \
+ rv = driver_name.init(pool, params, result); \
+ } \
+ *driver = &driver_name; \
+ }
+#endif
+
+static apr_status_t apr_crypto_term(void *ptr)
+{
+ /* set drivers to NULL so init can work again */
+ drivers = NULL;
+
+ /* Everything else we need is handled by cleanups registered
+ * when we created mutexes and loaded DSOs
+ */
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_crypto_init(apr_pool_t *pool)
+{
+ apr_status_t ret = APR_SUCCESS;
+ apr_pool_t *parent;
+
+ if (drivers != NULL) {
+ return APR_SUCCESS;
+ }
+
+ /* Top level pool scope, need process-scope lifetime */
+ for (parent = apr_pool_parent_get(pool);
+ parent && parent != pool;
+ parent = apr_pool_parent_get(pool))
+ pool = parent;
+#if APU_DSO_BUILD
+ /* deprecate in 2.0 - permit implicit initialization */
+ apu_dso_init(pool);
+#endif
+ drivers = apr_hash_make(pool);
+
+ apr_pool_cleanup_register(pool, NULL, apr_crypto_term,
+ apr_pool_cleanup_null);
+
+ return ret;
+}
+
+static apr_status_t crypto_clear(void *ptr)
+{
+ apr_crypto_clear_t *clear = (apr_crypto_clear_t *)ptr;
+
+ apr_crypto_memzero(clear->buffer, clear->size);
+ clear->buffer = NULL;
+ clear->size = 0;
+
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_crypto_clear(apr_pool_t *pool,
+ void *buffer, apr_size_t size)
+{
+ apr_crypto_clear_t *clear = apr_palloc(pool, sizeof(apr_crypto_clear_t));
+
+ clear->buffer = buffer;
+ clear->size = size;
+
+ apr_pool_cleanup_register(pool, clear, crypto_clear,
+ apr_pool_cleanup_null);
+
+ return APR_SUCCESS;
+}
+
+#if defined(HAVE_WEAK_SYMBOLS)
+void apr__memzero_explicit(void *buffer, apr_size_t size);
+
+__attribute__ ((weak))
+void apr__memzero_explicit(void *buffer, apr_size_t size)
+{
+ memset(buffer, 0, size);
+}
+#endif
+
+APU_DECLARE(apr_status_t) apr_crypto_memzero(void *buffer, apr_size_t size)
+{
+#if defined(WIN32)
+ SecureZeroMemory(buffer, size);
+#elif defined(HAVE_MEMSET_S)
+ if (size) {
+ return memset_s(buffer, (rsize_t)size, 0, (rsize_t)size);
+ }
+#elif defined(HAVE_EXPLICIT_BZERO)
+ explicit_bzero(buffer, size);
+#elif defined(HAVE_WEAK_SYMBOLS)
+ apr__memzero_explicit(buffer, size);
+#else
+ apr_size_t i;
+ volatile unsigned char *volatile ptr = buffer;
+ for (i = 0; i < size; ++i) {
+ ptr[i] = 0;
+ }
+#endif
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(int) apr_crypto_equals(const void *buf1, const void *buf2,
+ apr_size_t size)
+{
+ const unsigned char *p1 = buf1;
+ const unsigned char *p2 = buf2;
+ unsigned char diff = 0;
+ apr_size_t i;
+
+ for (i = 0; i < size; ++i) {
+ diff |= p1[i] ^ p2[i];
+ }
+
+ return 1 & ((diff - 1) >> 8);
+}
+
+APU_DECLARE(apr_status_t) apr_crypto_get_driver(
+ const apr_crypto_driver_t **driver, const char *name,
+ const char *params, const apu_err_t **result, apr_pool_t *pool)
+{
+#if APU_DSO_BUILD
+ char modname[32];
+ char symname[34];
+ apr_dso_handle_t *dso;
+ apr_dso_handle_sym_t symbol;
+#endif
+ apr_status_t rv;
+
+ if (result) {
+ *result = NULL; /* until further notice */
+ }
+
+#if APU_DSO_BUILD
+ rv = apu_dso_mutex_lock();
+ if (rv) {
+ return rv;
+ }
+#endif
+ *driver = apr_hash_get(drivers, name, APR_HASH_KEY_STRING);
+ if (*driver) {
+#if APU_DSO_BUILD
+ apu_dso_mutex_unlock();
+#endif
+ return APR_SUCCESS;
+ }
+
+ /* The driver must have exactly the same lifetime as the
+ * drivers hash table; ignore the passed-in pool */
+ pool = apr_hash_pool_get(drivers);
+
+#if APU_DSO_BUILD
+#if defined(NETWARE)
+ apr_snprintf(modname, sizeof(modname), "crypto%s.nlm", name);
+#elif defined(WIN32) || defined(__CYGWIN__)
+ apr_snprintf(modname, sizeof(modname),
+ "apr_crypto_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".dll", name);
+#else
+ apr_snprintf(modname, sizeof(modname),
+ "apr_crypto_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".so", name);
+#endif
+ apr_snprintf(symname, sizeof(symname), "apr_crypto_%s_driver", name);
+ rv = apu_dso_load(&dso, &symbol, modname, symname, pool);
+ if (rv == APR_SUCCESS || rv == APR_EINIT) { /* previously loaded?!? */
+ apr_crypto_driver_t *d = symbol;
+ rv = APR_SUCCESS;
+ if (d->init) {
+ rv = d->init(pool, params, result);
+ }
+ if (APR_SUCCESS == rv) {
+ *driver = symbol;
+ name = apr_pstrdup(pool, name);
+ apr_hash_set(drivers, name, APR_HASH_KEY_STRING, *driver);
+ }
+ }
+ apu_dso_mutex_unlock();
+
+ if (APR_SUCCESS != rv && result && !*result) {
+ char *buffer = apr_pcalloc(pool, ERROR_SIZE);
+ apu_err_t *err = apr_pcalloc(pool, sizeof(apu_err_t));
+ if (err && buffer) {
+ apr_dso_error(dso, buffer, ERROR_SIZE - 1);
+ err->msg = buffer;
+ err->reason = apr_pstrdup(pool, modname);
+ *result = err;
+ }
+ }
+
+#else /* not builtin and !APR_HAS_DSO => not implemented */
+ rv = APR_ENOTIMPL;
+
+ /* Load statically-linked drivers: */
+#if APU_HAVE_OPENSSL
+ if (name[0] == 'o' && !strcmp(name, "openssl")) {
+ DRIVER_LOAD("openssl", apr_crypto_openssl_driver, pool, params, rv, result);
+ }
+#endif
+#if APU_HAVE_NSS
+ if (name[0] == 'n' && !strcmp(name, "nss")) {
+ DRIVER_LOAD("nss", apr_crypto_nss_driver, pool, params, rv, result);
+ }
+#endif
+#if APU_HAVE_COMMONCRYPTO
+ if (name[0] == 'c' && !strcmp(name, "commoncrypto")) {
+ DRIVER_LOAD("commoncrypto", apr_crypto_commoncrypto_driver, pool, params, rv, result);
+ }
+#endif
+#if APU_HAVE_MSCAPI
+ if (name[0] == 'm' && !strcmp(name, "mscapi")) {
+ DRIVER_LOAD("mscapi", apr_crypto_mscapi_driver, pool, params, rv, result);
+ }
+#endif
+#if APU_HAVE_MSCNG
+ if (name[0] == 'm' && !strcmp(name, "mscng")) {
+ DRIVER_LOAD("mscng", apr_crypto_mscng_driver, pool, params, rv, result);
+ }
+#endif
+
+#endif
+
+ return rv;
+}
+
+/**
+ * @brief Return the name of the driver.
+ *
+ * @param driver - The driver in use.
+ * @return The name of the driver.
+ */
+APU_DECLARE(const char *)apr_crypto_driver_name (
+ const apr_crypto_driver_t *driver)
+{
+ return driver->name;
+}
+
+/**
+ * @brief Get the result of the last operation on a context. If the result
+ * is NULL, the operation was successful.
+ * @param result - the result structure
+ * @param f - context pointer
+ * @return APR_SUCCESS for success
+ */
+APU_DECLARE(apr_status_t) apr_crypto_error(const apu_err_t **result,
+ const apr_crypto_t *f)
+{
+ return f->provider->error(result, f);
+}
+
+/**
+ * @brief Create a context for supporting encryption. Keys, certificates,
+ * algorithms and other parameters will be set per context. More than
+ * one context can be created at one time. A cleanup will be automatically
+ * registered with the given pool to guarantee a graceful shutdown.
+ * @param f - context pointer will be written here
+ * @param driver - driver to use
+ * @param params - array of key parameters
+ * @param pool - process pool
+ * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
+ * if the engine cannot be initialised.
+ * @remarks NSS: currently no params are supported.
+ * @remarks OpenSSL: the params can have "engine" as a key, followed by an equal
+ * sign and a value.
+ */
+APU_DECLARE(apr_status_t) apr_crypto_make(apr_crypto_t **f,
+ const apr_crypto_driver_t *driver, const char *params, apr_pool_t *pool)
+{
+ return driver->make(f, driver, params, pool);
+}
+
+/**
+ * @brief Get a hash table of key types, keyed by the name of the type against
+ * a pointer to apr_crypto_block_key_type_t, which in turn begins with an
+ * integer.
+ *
+ * @param types - hashtable of key types keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+APU_DECLARE(apr_status_t) apr_crypto_get_block_key_types(apr_hash_t **types,
+ const apr_crypto_t *f)
+{
+ return f->provider->get_block_key_types(types, f);
+}
+
+/**
+ * @brief Get a hash table of key modes, keyed by the name of the mode against
+ * a pointer to apr_crypto_block_key_mode_t, which in turn begins with an
+ * integer.
+ *
+ * @param modes - hashtable of key modes keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+APU_DECLARE(apr_status_t) apr_crypto_get_block_key_modes(apr_hash_t **modes,
+ const apr_crypto_t *f)
+{
+ return f->provider->get_block_key_modes(modes, f);
+}
+
+/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ * up when the context is cleaned, and may be reused with multiple encryption
+ * or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+APU_DECLARE(apr_status_t) apr_crypto_key(apr_crypto_key_t **key,
+ const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
+{
+ return f->provider->key(key, rec, f, p);
+}
+
+/**
+ * @brief Create a key from the given passphrase. By default, the PBKDF2
+ * algorithm is used to generate the key from the passphrase. It is expected
+ * that the same pass phrase will generate the same key, regardless of the
+ * backend crypto platform used. The key is cleaned up when the context
+ * is cleaned, and may be reused with multiple encryption or decryption
+ * operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param ivSize The size of the initialisation vector will be returned, based
+ * on whether an IV is relevant for this type of crypto.
+ * @param pass The passphrase to use.
+ * @param passLen The passphrase length in bytes
+ * @param salt The salt to use.
+ * @param saltLen The salt length in bytes
+ * @param type 3DES_192, AES_128, AES_192, AES_256.
+ * @param mode Electronic Code Book / Cipher Block Chaining.
+ * @param doPad Pad if necessary.
+ * @param iterations Number of iterations to use in algorithm
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+APU_DECLARE(apr_status_t) apr_crypto_passphrase(apr_crypto_key_t **key,
+ apr_size_t *ivSize, const char *pass, apr_size_t passLen,
+ const unsigned char * salt, apr_size_t saltLen,
+ const apr_crypto_block_key_type_e type,
+ const apr_crypto_block_key_mode_e mode, const int doPad,
+ const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+{
+ return f->provider->passphrase(key, ivSize, pass, passLen, salt, saltLen,
+ type, mode, doPad, iterations, f, p);
+}
+
+/**
+ * @brief Initialise a context for encrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ * *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ * an IV will be created at random, in space allocated from the pool.
+ * If the buffer pointed to is not NULL, the IV in the buffer will be
+ * used.
+ * @param key The key structure to use.
+ * @param blockSize The block size of the cipher.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ * Returns APR_EINIT if the backend failed to initialise the context. Returns
+ * APR_ENOTIMPL if not implemented.
+ */
+APU_DECLARE(apr_status_t) apr_crypto_block_encrypt_init(
+ apr_crypto_block_t **ctx, const unsigned char **iv,
+ const apr_crypto_key_t *key, apr_size_t *blockSize, apr_pool_t *p)
+{
+ return key->provider->block_encrypt_init(ctx, iv, key, blockSize, p);
+}
+
+/**
+ * @brief Encrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ * out is NULL, outlen will contain the maximum size of the
+ * buffer needed to hold the data, including any data
+ * generated by apr_crypto_block_encrypt_finish below. If *out points
+ * to NULL, a buffer sufficiently large will be created from
+ * the pool provided. If *out points to a not-NULL value, this
+ * value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ * see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ * not implemented.
+ */
+APU_DECLARE(apr_status_t) apr_crypto_block_encrypt(unsigned char **out,
+ apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+ apr_crypto_block_t *ctx)
+{
+ return ctx->provider->block_encrypt(out, outlen, in, inlen, ctx);
+}
+
+/**
+ * @brief Encrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ * padded. Typically the final block will be written to the
+ * same buffer used by apr_crypto_block_encrypt, offset by the
+ * number of bytes returned as actually written by the
+ * apr_crypto_block_encrypt() call. After this call, the context
+ * is cleaned and can be reused by apr_crypto_block_encrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ * buffer must already exist, and is usually the same
+ * buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ * formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+APU_DECLARE(apr_status_t) apr_crypto_block_encrypt_finish(unsigned char *out,
+ apr_size_t *outlen, apr_crypto_block_t *ctx)
+{
+ return ctx->provider->block_encrypt_finish(out, outlen, ctx);
+}
+
+/**
+ * @brief Initialise a context for decrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ * *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param blockSize The block size of the cipher.
+ * @param iv Optional initialisation vector.
+ * @param key The key structure to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ * Returns APR_EINIT if the backend failed to initialise the context. Returns
+ * APR_ENOTIMPL if not implemented.
+ */
+APU_DECLARE(apr_status_t) apr_crypto_block_decrypt_init(
+ apr_crypto_block_t **ctx, apr_size_t *blockSize,
+ const unsigned char *iv, const apr_crypto_key_t *key, apr_pool_t *p)
+{
+ return key->provider->block_decrypt_init(ctx, blockSize, iv, key, p);
+}
+
+/**
+ * @brief Decrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ * out is NULL, outlen will contain the maximum size of the
+ * buffer needed to hold the data, including any data
+ * generated by apr_crypto_block_decrypt_finish below. If *out points
+ * to NULL, a buffer sufficiently large will be created from
+ * the pool provided. If *out points to a not-NULL value, this
+ * value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ * see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ * not implemented.
+ */
+APU_DECLARE(apr_status_t) apr_crypto_block_decrypt(unsigned char **out,
+ apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+ apr_crypto_block_t *ctx)
+{
+ return ctx->provider->block_decrypt(out, outlen, in, inlen, ctx);
+}
+
+/**
+ * @brief Decrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ * padded. Typically the final block will be written to the
+ * same buffer used by apr_crypto_block_decrypt, offset by the
+ * number of bytes returned as actually written by the
+ * apr_crypto_block_decrypt() call. After this call, the context
+ * is cleaned and can be reused by apr_crypto_block_decrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ * buffer must already exist, and is usually the same
+ * buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ * formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+APU_DECLARE(apr_status_t) apr_crypto_block_decrypt_finish(unsigned char *out,
+ apr_size_t *outlen, apr_crypto_block_t *ctx)
+{
+ return ctx->provider->block_decrypt_finish(out, outlen, ctx);
+}
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param ctx The block context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+APU_DECLARE(apr_status_t) apr_crypto_block_cleanup(apr_crypto_block_t *ctx)
+{
+ return ctx->provider->block_cleanup(ctx);
+}
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param f The context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+APU_DECLARE(apr_status_t) apr_crypto_cleanup(apr_crypto_t *f)
+{
+ return f->provider->cleanup(f);
+}
+
+/**
+ * @brief Shutdown the crypto library.
+ * @note After shutdown, it is expected that the init function can be called again.
+ * @param driver - driver to use
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+APU_DECLARE(apr_status_t) apr_crypto_shutdown(const apr_crypto_driver_t *driver)
+{
+ return driver->shutdown();
+}
+
+#endif /* APU_HAVE_CRYPTO */
diff --git a/crypto/apr_crypto_commoncrypto.c b/crypto/apr_crypto_commoncrypto.c
new file mode 100644
index 0000000..81b0299
--- /dev/null
+++ b/crypto/apr_crypto_commoncrypto.c
@@ -0,0 +1,906 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_lib.h"
+#include "apu.h"
+#include "apu_errno.h"
+
+#include <ctype.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "apr_strings.h"
+#include "apr_time.h"
+#include "apr_buckets.h"
+#include "apr_random.h"
+
+#include "apr_crypto_internal.h"
+
+#if APU_HAVE_CRYPTO
+
+#include <CommonCrypto/CommonCrypto.h>
+
+#define LOG_PREFIX "apr_crypto_commoncrypto: "
+
+struct apr_crypto_t
+{
+ apr_pool_t *pool;
+ const apr_crypto_driver_t *provider;
+ apu_err_t *result;
+ apr_hash_t *types;
+ apr_hash_t *modes;
+ apr_random_t *rng;
+};
+
+struct apr_crypto_key_t
+{
+ apr_pool_t *pool;
+ const apr_crypto_driver_t *provider;
+ const apr_crypto_t *f;
+ CCAlgorithm algorithm;
+ CCOptions options;
+ unsigned char *key;
+ int keyLen;
+ int ivSize;
+ apr_size_t blockSize;
+};
+
+struct apr_crypto_block_t
+{
+ apr_pool_t *pool;
+ const apr_crypto_driver_t *provider;
+ const apr_crypto_t *f;
+ const apr_crypto_key_t *key;
+ CCCryptorRef ref;
+};
+
+static struct apr_crypto_block_key_type_t key_types[] =
+{
+{ APR_KEY_3DES_192, 24, 8, 8 },
+{ APR_KEY_AES_128, 16, 16, 16 },
+{ APR_KEY_AES_192, 24, 16, 16 },
+{ APR_KEY_AES_256, 32, 16, 16 } };
+
+static struct apr_crypto_block_key_mode_t key_modes[] =
+{
+{ APR_MODE_ECB },
+{ APR_MODE_CBC } };
+
+/**
+ * Fetch the most recent error from this driver.
+ */
+static apr_status_t crypto_error(const apu_err_t **result,
+ const apr_crypto_t *f)
+{
+ *result = f->result;
+ return APR_SUCCESS;
+}
+
+/**
+ * Shutdown the crypto library and release resources.
+ */
+static apr_status_t crypto_shutdown(void)
+{
+ return APR_SUCCESS;
+}
+
+static apr_status_t crypto_shutdown_helper(void *data)
+{
+ return crypto_shutdown();
+}
+
+/**
+ * Initialise the crypto library and perform one time initialisation.
+ */
+static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
+ const apu_err_t **result)
+{
+
+ apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper,
+ apr_pool_cleanup_null);
+
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param ctx The block context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+static apr_status_t crypto_block_cleanup(apr_crypto_block_t *ctx)
+{
+
+ if (ctx->ref) {
+ CCCryptorRelease(ctx->ref);
+ ctx->ref = NULL;
+ }
+
+ return APR_SUCCESS;
+
+}
+
+static apr_status_t crypto_block_cleanup_helper(void *data)
+{
+ apr_crypto_block_t *block = (apr_crypto_block_t *) data;
+ return crypto_block_cleanup(block);
+}
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param f The context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+static apr_status_t crypto_cleanup(apr_crypto_t *f)
+{
+
+ return APR_SUCCESS;
+
+}
+
+static apr_status_t crypto_cleanup_helper(void *data)
+{
+ apr_crypto_t *f = (apr_crypto_t *) data;
+ return crypto_cleanup(f);
+}
+
+/**
+ * @brief Create a context for supporting encryption. Keys, certificates,
+ * algorithms and other parameters will be set per context. More than
+ * one context can be created at one time. A cleanup will be automatically
+ * registered with the given pool to guarantee a graceful shutdown.
+ * @param f - context pointer will be written here
+ * @param provider - provider to use
+ * @param params - array of key parameters
+ * @param pool - process pool
+ * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
+ * if the engine cannot be initialised.
+ */
+static apr_status_t crypto_make(apr_crypto_t **ff,
+ const apr_crypto_driver_t *provider, const char *params,
+ apr_pool_t *pool)
+{
+ apr_crypto_t *f = apr_pcalloc(pool, sizeof(apr_crypto_t));
+ apr_status_t rv;
+
+ if (!f) {
+ return APR_ENOMEM;
+ }
+ *ff = f;
+ f->pool = pool;
+ f->provider = provider;
+
+ /* seed the secure random number generator */
+ f->rng = apr_random_standard_new(pool);
+ if (!f->rng) {
+ return APR_ENOMEM;
+ }
+ do {
+ unsigned char seed[8];
+ rv = apr_generate_random_bytes(seed, sizeof(seed));
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ apr_random_add_entropy(f->rng, seed, sizeof(seed));
+ rv = apr_random_secure_ready(f->rng);
+ } while (rv == APR_ENOTENOUGHENTROPY);
+
+ f->result = apr_pcalloc(pool, sizeof(apu_err_t));
+ if (!f->result) {
+ return APR_ENOMEM;
+ }
+
+ f->types = apr_hash_make(pool);
+ if (!f->types) {
+ return APR_ENOMEM;
+ }
+ apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0]));
+ apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1]));
+ apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_types[2]));
+ apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_types[3]));
+
+ f->modes = apr_hash_make(pool);
+ if (!f->modes) {
+ return APR_ENOMEM;
+ }
+ apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0]));
+ apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1]));
+
+ apr_pool_cleanup_register(pool, f, crypto_cleanup_helper,
+ apr_pool_cleanup_null);
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Get a hash table of key types, keyed by the name of the type against
+ * a pointer to apr_crypto_block_key_type_t.
+ *
+ * @param types - hashtable of key types keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+static apr_status_t crypto_get_block_key_types(apr_hash_t **types,
+ const apr_crypto_t *f)
+{
+ *types = f->types;
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Get a hash table of key modes, keyed by the name of the mode against
+ * a pointer to apr_crypto_block_key_mode_t.
+ *
+ * @param modes - hashtable of key modes keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+static apr_status_t crypto_get_block_key_modes(apr_hash_t **modes,
+ const apr_crypto_t *f)
+{
+ *modes = f->modes;
+ return APR_SUCCESS;
+}
+
+/*
+ * Work out which mechanism to use.
+ */
+static apr_status_t crypto_cipher_mechanism(apr_crypto_key_t *key,
+ const apr_crypto_block_key_type_e type,
+ const apr_crypto_block_key_mode_e mode, const int doPad, apr_pool_t *p)
+{
+ /* handle padding */
+ key->options = doPad ? kCCOptionPKCS7Padding : 0;
+
+ /* determine the algorithm to be used */
+ switch (type) {
+
+ case (APR_KEY_3DES_192):
+
+ /* A 3DES key */
+ if (mode == APR_MODE_CBC) {
+ key->algorithm = kCCAlgorithm3DES;
+ key->keyLen = kCCKeySize3DES;
+ key->ivSize = kCCBlockSize3DES;
+ key->blockSize = kCCBlockSize3DES;
+ }
+ else {
+ key->algorithm = kCCAlgorithm3DES;
+ key->options += kCCOptionECBMode;
+ key->keyLen = kCCKeySize3DES;
+ key->ivSize = 0;
+ key->blockSize = kCCBlockSize3DES;
+ }
+ break;
+
+ case (APR_KEY_AES_128):
+
+ if (mode == APR_MODE_CBC) {
+ key->algorithm = kCCAlgorithmAES128;
+ key->keyLen = kCCKeySizeAES128;
+ key->ivSize = kCCBlockSizeAES128;
+ key->blockSize = kCCBlockSizeAES128;
+ }
+ else {
+ key->algorithm = kCCAlgorithmAES128;
+ key->options += kCCOptionECBMode;
+ key->keyLen = kCCKeySizeAES128;
+ key->ivSize = 0;
+ key->blockSize = kCCBlockSizeAES128;
+ }
+ break;
+
+ case (APR_KEY_AES_192):
+
+ if (mode == APR_MODE_CBC) {
+ key->algorithm = kCCAlgorithmAES128;
+ key->keyLen = kCCKeySizeAES192;
+ key->ivSize = kCCBlockSizeAES128;
+ key->blockSize = kCCBlockSizeAES128;
+ }
+ else {
+ key->algorithm = kCCAlgorithmAES128;
+ key->options += kCCOptionECBMode;
+ key->keyLen = kCCKeySizeAES192;
+ key->ivSize = 0;
+ key->blockSize = kCCBlockSizeAES128;
+ }
+ break;
+
+ case (APR_KEY_AES_256):
+
+ if (mode == APR_MODE_CBC) {
+ key->algorithm = kCCAlgorithmAES128;
+ key->keyLen = kCCKeySizeAES256;
+ key->ivSize = kCCBlockSizeAES128;
+ key->blockSize = kCCBlockSizeAES128;
+ }
+ else {
+ key->algorithm = kCCAlgorithmAES128;
+ key->options += kCCOptionECBMode;
+ key->keyLen = kCCKeySizeAES256;
+ key->ivSize = 0;
+ key->blockSize = kCCBlockSizeAES128;
+ }
+ break;
+
+ default:
+
+ /* TODO: Support CAST, Blowfish */
+
+ /* unknown key type, give up */
+ return APR_EKEYTYPE;
+
+ }
+
+ /* make space for the key */
+ key->key = apr_palloc(p, key->keyLen);
+ if (!key->key) {
+ return APR_ENOMEM;
+ }
+ apr_crypto_clear(p, key->key, key->keyLen);
+
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ * up when the context is cleaned, and may be reused with multiple encryption
+ * or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_key(apr_crypto_key_t **k,
+ const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
+{
+ apr_status_t rv;
+ apr_crypto_key_t *key = *k;
+
+ if (!key) {
+ *k = key = apr_pcalloc(p, sizeof *key);
+ }
+ if (!key) {
+ return APR_ENOMEM;
+ }
+
+ key->f = f;
+ key->provider = f->provider;
+
+ /* decide on what cipher mechanism we will be using */
+ rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad, p);
+ if (APR_SUCCESS != rv) {
+ return rv;
+ }
+
+ switch (rec->ktype) {
+
+ case APR_CRYPTO_KTYPE_PASSPHRASE: {
+
+ /* generate the key */
+ if ((f->result->rc = CCKeyDerivationPBKDF(kCCPBKDF2,
+ rec->k.passphrase.pass, rec->k.passphrase.passLen,
+ rec->k.passphrase.salt, rec->k.passphrase.saltLen,
+ kCCPRFHmacAlgSHA1, rec->k.passphrase.iterations, key->key,
+ key->keyLen)) == kCCParamError) {
+ return APR_ENOKEY;
+ }
+
+ break;
+ }
+
+ case APR_CRYPTO_KTYPE_SECRET: {
+
+ /* sanity check - key correct size? */
+ if (rec->k.secret.secretLen != key->keyLen) {
+ return APR_EKEYLENGTH;
+ }
+
+ /* copy the key */
+ memcpy(key->key, rec->k.secret.secret, rec->k.secret.secretLen);
+
+ break;
+ }
+
+ default: {
+
+ return APR_ENOKEY;
+
+ }
+ }
+
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the given passphrase. By default, the PBKDF2
+ * algorithm is used to generate the key from the passphrase. It is expected
+ * that the same pass phrase will generate the same key, regardless of the
+ * backend crypto platform used. The key is cleaned up when the context
+ * is cleaned, and may be reused with multiple encryption or decryption
+ * operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param ivSize The size of the initialisation vector will be returned, based
+ * on whether an IV is relevant for this type of crypto.
+ * @param pass The passphrase to use.
+ * @param passLen The passphrase length in bytes
+ * @param salt The salt to use.
+ * @param saltLen The salt length in bytes
+ * @param type 3DES_192, AES_128, AES_192, AES_256.
+ * @param mode Electronic Code Book / Cipher Block Chaining.
+ * @param doPad Pad if necessary.
+ * @param iterations Iteration count
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
+ const char *pass, apr_size_t passLen, const unsigned char * salt,
+ apr_size_t saltLen, const apr_crypto_block_key_type_e type,
+ const apr_crypto_block_key_mode_e mode, const int doPad,
+ const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+{
+ apr_status_t rv;
+ apr_crypto_key_t *key = *k;
+
+ if (!key) {
+ *k = key = apr_pcalloc(p, sizeof *key);
+ if (!key) {
+ return APR_ENOMEM;
+ }
+ }
+
+ key->f = f;
+ key->provider = f->provider;
+
+ /* decide on what cipher mechanism we will be using */
+ rv = crypto_cipher_mechanism(key, type, mode, doPad, p);
+ if (APR_SUCCESS != rv) {
+ return rv;
+ }
+
+ /* generate the key */
+ if ((f->result->rc = CCKeyDerivationPBKDF(kCCPBKDF2, pass, passLen, salt,
+ saltLen, kCCPRFHmacAlgSHA1, iterations, key->key, key->keyLen))
+ == kCCParamError) {
+ return APR_ENOKEY;
+ }
+
+ if (ivSize) {
+ *ivSize = key->ivSize;
+ }
+
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Initialise a context for encrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ * *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ * an IV will be created at random, in space allocated from the pool.
+ * If the buffer pointed to is not NULL, the IV in the buffer will be
+ * used.
+ * @param key The key structure.
+ * @param blockSize The block size of the cipher.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ * Returns APR_EINIT if the backend failed to initialise the context. Returns
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
+ const unsigned char **iv, const apr_crypto_key_t *key,
+ apr_size_t *blockSize, apr_pool_t *p)
+{
+ unsigned char *usedIv;
+ apr_crypto_block_t *block = *ctx;
+ if (!block) {
+ *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
+ }
+ if (!block) {
+ return APR_ENOMEM;
+ }
+ block->f = key->f;
+ block->pool = p;
+ block->provider = key->provider;
+ block->key = key;
+
+ apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
+ apr_pool_cleanup_null);
+
+ /* generate an IV, if necessary */
+ usedIv = NULL;
+ if (key->ivSize) {
+ if (iv == NULL) {
+ return APR_ENOIV;
+ }
+ if (*iv == NULL) {
+ apr_status_t status;
+ usedIv = apr_pcalloc(p, key->ivSize);
+ if (!usedIv) {
+ return APR_ENOMEM;
+ }
+ apr_crypto_clear(p, usedIv, key->ivSize);
+ status = apr_random_secure_bytes(block->f->rng, usedIv,
+ key->ivSize);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+ *iv = usedIv;
+ }
+ else {
+ usedIv = (unsigned char *) *iv;
+ }
+ }
+
+ /* create a new context for encryption */
+ switch ((block->f->result->rc = CCCryptorCreate(kCCEncrypt, key->algorithm,
+ key->options, key->key, key->keyLen, usedIv, &block->ref))) {
+ case kCCSuccess: {
+ break;
+ }
+ case kCCParamError: {
+ return APR_EINIT;
+ }
+ case kCCMemoryFailure: {
+ return APR_ENOMEM;
+ }
+ case kCCAlignmentError: {
+ return APR_EPADDING;
+ }
+ case kCCUnimplemented: {
+ return APR_ENOTIMPL;
+ }
+ default: {
+ return APR_EINIT;
+ }
+ }
+
+ if (blockSize) {
+ *blockSize = key->blockSize;
+ }
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Encrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ * out is NULL, outlen will contain the maximum size of the
+ * buffer needed to hold the data, including any data
+ * generated by apr_crypto_block_encrypt_finish below. If *out points
+ * to NULL, a buffer sufficiently large will be created from
+ * the pool provided. If *out points to a not-NULL value, this
+ * value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ * see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ * not implemented.
+ */
+static apr_status_t crypto_block_encrypt(unsigned char **out,
+ apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+ apr_crypto_block_t *ctx)
+{
+ apr_size_t outl = *outlen;
+ unsigned char *buffer;
+
+ /* are we after the maximum size of the out buffer? */
+ if (!out) {
+ *outlen = CCCryptorGetOutputLength(ctx->ref, inlen, 1);
+ return APR_SUCCESS;
+ }
+
+ /* must we allocate the output buffer from a pool? */
+ if (!*out) {
+ outl = CCCryptorGetOutputLength(ctx->ref, inlen, 1);
+ buffer = apr_palloc(ctx->pool, outl);
+ if (!buffer) {
+ return APR_ENOMEM;
+ }
+ apr_crypto_clear(ctx->pool, buffer, outl);
+ *out = buffer;
+ }
+
+ switch ((ctx->f->result->rc = CCCryptorUpdate(ctx->ref, in, inlen, (*out),
+ outl, &outl))) {
+ case kCCSuccess: {
+ break;
+ }
+ case kCCBufferTooSmall: {
+ return APR_ENOSPACE;
+ }
+ default: {
+ return APR_ECRYPT;
+ }
+ }
+ *outlen = outl;
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Encrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ * padded. Typically the final block will be written to the
+ * same buffer used by apr_crypto_block_encrypt, offset by the
+ * number of bytes returned as actually written by the
+ * apr_crypto_block_encrypt() call. After this call, the context
+ * is cleaned and can be reused by apr_crypto_block_encrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ * buffer must already exist, and is usually the same
+ * buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ * formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_encrypt_finish(unsigned char *out,
+ apr_size_t *outlen, apr_crypto_block_t *ctx)
+{
+ apr_size_t len = *outlen;
+
+ ctx->f->result->rc = CCCryptorFinal(ctx->ref, out,
+ CCCryptorGetOutputLength(ctx->ref, 0, 1), &len);
+
+ /* always clean up */
+ crypto_block_cleanup(ctx);
+
+ switch (ctx->f->result->rc) {
+ case kCCSuccess: {
+ break;
+ }
+ case kCCBufferTooSmall: {
+ return APR_ENOSPACE;
+ }
+ case kCCAlignmentError: {
+ return APR_EPADDING;
+ }
+ case kCCDecodeError: {
+ return APR_ECRYPT;
+ }
+ default: {
+ return APR_ECRYPT;
+ }
+ }
+ *outlen = len;
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Initialise a context for decrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ * *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param blockSize The block size of the cipher.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ * an IV will be created at random, in space allocated from the pool.
+ * If the buffer is not NULL, the IV in the buffer will be used.
+ * @param key The key structure.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ * Returns APR_EINIT if the backend failed to initialise the context. Returns
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
+ apr_size_t *blockSize, const unsigned char *iv,
+ const apr_crypto_key_t *key, apr_pool_t *p)
+{
+ apr_crypto_block_t *block = *ctx;
+ if (!block) {
+ *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
+ }
+ if (!block) {
+ return APR_ENOMEM;
+ }
+ block->f = key->f;
+ block->pool = p;
+ block->provider = key->provider;
+
+ apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
+ apr_pool_cleanup_null);
+
+ /* generate an IV, if necessary */
+ if (key->ivSize) {
+ if (iv == NULL) {
+ return APR_ENOIV;
+ }
+ }
+
+ /* create a new context for decryption */
+ switch ((block->f->result->rc = CCCryptorCreate(kCCDecrypt, key->algorithm,
+ key->options, key->key, key->keyLen, iv, &block->ref))) {
+ case kCCSuccess: {
+ break;
+ }
+ case kCCParamError: {
+ return APR_EINIT;
+ }
+ case kCCMemoryFailure: {
+ return APR_ENOMEM;
+ }
+ case kCCAlignmentError: {
+ return APR_EPADDING;
+ }
+ case kCCUnimplemented: {
+ return APR_ENOTIMPL;
+ }
+ default: {
+ return APR_EINIT;
+ }
+ }
+
+ if (blockSize) {
+ *blockSize = key->blockSize;
+ }
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Decrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ * out is NULL, outlen will contain the maximum size of the
+ * buffer needed to hold the data, including any data
+ * generated by apr_crypto_block_decrypt_finish below. If *out points
+ * to NULL, a buffer sufficiently large will be created from
+ * the pool provided. If *out points to a not-NULL value, this
+ * value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ * see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ * not implemented.
+ */
+static apr_status_t crypto_block_decrypt(unsigned char **out,
+ apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+ apr_crypto_block_t *ctx)
+{
+ apr_size_t outl = *outlen;
+ unsigned char *buffer;
+
+ /* are we after the maximum size of the out buffer? */
+ if (!out) {
+ *outlen = CCCryptorGetOutputLength(ctx->ref, inlen, 1);
+ return APR_SUCCESS;
+ }
+
+ /* must we allocate the output buffer from a pool? */
+ if (!*out) {
+ outl = CCCryptorGetOutputLength(ctx->ref, inlen, 1);
+ buffer = apr_palloc(ctx->pool, outl);
+ if (!buffer) {
+ return APR_ENOMEM;
+ }
+ apr_crypto_clear(ctx->pool, buffer, outl);
+ *out = buffer;
+ }
+
+ switch ((ctx->f->result->rc = CCCryptorUpdate(ctx->ref, in, inlen, (*out),
+ outl, &outl))) {
+ case kCCSuccess: {
+ break;
+ }
+ case kCCBufferTooSmall: {
+ return APR_ENOSPACE;
+ }
+ default: {
+ return APR_ECRYPT;
+ }
+ }
+ *outlen = outl;
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Decrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ * padded. Typically the final block will be written to the
+ * same buffer used by apr_crypto_block_decrypt, offset by the
+ * number of bytes returned as actually written by the
+ * apr_crypto_block_decrypt() call. After this call, the context
+ * is cleaned and can be reused by apr_crypto_block_decrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ * buffer must already exist, and is usually the same
+ * buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ * formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_decrypt_finish(unsigned char *out,
+ apr_size_t *outlen, apr_crypto_block_t *ctx)
+{
+ apr_size_t len = *outlen;
+
+ ctx->f->result->rc = CCCryptorFinal(ctx->ref, out,
+ CCCryptorGetOutputLength(ctx->ref, 0, 1), &len);
+
+ /* always clean up */
+ crypto_block_cleanup(ctx);
+
+ switch (ctx->f->result->rc) {
+ case kCCSuccess: {
+ break;
+ }
+ case kCCBufferTooSmall: {
+ return APR_ENOSPACE;
+ }
+ case kCCAlignmentError: {
+ return APR_EPADDING;
+ }
+ case kCCDecodeError: {
+ return APR_ECRYPT;
+ }
+ default: {
+ return APR_ECRYPT;
+ }
+ }
+ *outlen = len;
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * OSX Common Crypto module.
+ */
+APU_MODULE_DECLARE_DATA const apr_crypto_driver_t apr_crypto_commoncrypto_driver =
+{
+ "commoncrypto", crypto_init, crypto_make, crypto_get_block_key_types,
+ crypto_get_block_key_modes, crypto_passphrase,
+ crypto_block_encrypt_init, crypto_block_encrypt,
+ crypto_block_encrypt_finish, crypto_block_decrypt_init,
+ crypto_block_decrypt, crypto_block_decrypt_finish, crypto_block_cleanup,
+ crypto_cleanup, crypto_shutdown, crypto_error, crypto_key
+};
+
+#endif
diff --git a/crypto/apr_crypto_nss.c b/crypto/apr_crypto_nss.c
new file mode 100644
index 0000000..47d1640
--- /dev/null
+++ b/crypto/apr_crypto_nss.c
@@ -0,0 +1,1097 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_lib.h"
+#include "apu.h"
+#include "apu_config.h"
+#include "apu_errno.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include "apr_strings.h"
+#include "apr_time.h"
+#include "apr_buckets.h"
+
+#include "apr_crypto_internal.h"
+
+#if APU_HAVE_CRYPTO
+
+#include <prerror.h>
+
+#ifdef HAVE_NSS_NSS_H
+#include <nss/nss.h>
+#endif
+#ifdef HAVE_NSS_H
+#include <nss.h>
+#endif
+
+#ifdef HAVE_NSS_PK11PUB_H
+#include <nss/pk11pub.h>
+#endif
+#ifdef HAVE_PK11PUB_H
+#include <pk11pub.h>
+#endif
+
+struct apr_crypto_t {
+ apr_pool_t *pool;
+ const apr_crypto_driver_t *provider;
+ apu_err_t *result;
+ apr_crypto_config_t *config;
+ apr_hash_t *types;
+ apr_hash_t *modes;
+};
+
+struct apr_crypto_config_t {
+ void *opaque;
+};
+
+struct apr_crypto_key_t {
+ apr_pool_t *pool;
+ const apr_crypto_driver_t *provider;
+ const apr_crypto_t *f;
+ CK_MECHANISM_TYPE cipherMech;
+ SECOidTag cipherOid;
+ PK11SymKey *symKey;
+ int ivSize;
+ int keyLength;
+};
+
+struct apr_crypto_block_t {
+ apr_pool_t *pool;
+ const apr_crypto_driver_t *provider;
+ const apr_crypto_t *f;
+ PK11Context *ctx;
+ apr_crypto_key_t *key;
+ SECItem *secParam;
+ int blockSize;
+};
+
+static struct apr_crypto_block_key_type_t key_types[] =
+{
+{ APR_KEY_3DES_192, 24, 8, 8 },
+{ APR_KEY_AES_128, 16, 16, 16 },
+{ APR_KEY_AES_192, 24, 16, 16 },
+{ APR_KEY_AES_256, 32, 16, 16 } };
+
+static struct apr_crypto_block_key_mode_t key_modes[] =
+{
+{ APR_MODE_ECB },
+{ APR_MODE_CBC } };
+
+/* sufficient space to wrap a key */
+#define BUFFER_SIZE 128
+
+/**
+ * Fetch the most recent error from this driver.
+ */
+static apr_status_t crypto_error(const apu_err_t **result,
+ const apr_crypto_t *f)
+{
+ *result = f->result;
+ return APR_SUCCESS;
+}
+
+/**
+ * Shutdown the crypto library and release resources.
+ *
+ * It is safe to shut down twice.
+ */
+static apr_status_t crypto_shutdown(void)
+{
+ if (NSS_IsInitialized()) {
+ SECStatus s = NSS_Shutdown();
+ if (s != SECSuccess) {
+ fprintf(stderr, "NSS failed to shutdown, possible leak: %d: %s",
+ PR_GetError(), PR_ErrorToName(s));
+ return APR_EINIT;
+ }
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t crypto_shutdown_helper(void *data)
+{
+ return crypto_shutdown();
+}
+
+/**
+ * Initialise the crypto library and perform one time initialisation.
+ */
+static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
+ const apu_err_t **result)
+{
+ SECStatus s;
+ const char *dir = NULL;
+ const char *keyPrefix = NULL;
+ const char *certPrefix = NULL;
+ const char *secmod = NULL;
+ int noinit = 0;
+ PRUint32 flags = 0;
+
+ struct {
+ const char *field;
+ const char *value;
+ int set;
+ } fields[] = {
+ { "dir", NULL, 0 },
+ { "key3", NULL, 0 },
+ { "cert7", NULL, 0 },
+ { "secmod", NULL, 0 },
+ { "noinit", NULL, 0 },
+ { NULL, NULL, 0 }
+ };
+ const char *ptr;
+ size_t klen;
+ char **elts = NULL;
+ char *elt;
+ int i = 0, j;
+ apr_status_t status;
+
+ if (params) {
+ if (APR_SUCCESS != (status = apr_tokenize_to_argv(params, &elts, pool))) {
+ return status;
+ }
+ while ((elt = elts[i])) {
+ ptr = strchr(elt, '=');
+ if (ptr) {
+ for (klen = ptr - elt; klen && apr_isspace(elt[klen - 1]); --klen)
+ ;
+ ptr++;
+ }
+ else {
+ for (klen = strlen(elt); klen && apr_isspace(elt[klen - 1]); --klen)
+ ;
+ }
+ elt[klen] = 0;
+
+ for (j = 0; fields[j].field != NULL; ++j) {
+ if (klen && !strcasecmp(fields[j].field, elt)) {
+ fields[j].set = 1;
+ if (ptr) {
+ fields[j].value = ptr;
+ }
+ break;
+ }
+ }
+
+ i++;
+ }
+ dir = fields[0].value;
+ keyPrefix = fields[1].value;
+ certPrefix = fields[2].value;
+ secmod = fields[3].value;
+ noinit = fields[4].set;
+ }
+
+ /* if we've been asked to bypass, do so here */
+ if (noinit) {
+ return APR_SUCCESS;
+ }
+
+ /* sanity check - we can only initialise NSS once */
+ if (NSS_IsInitialized()) {
+ return APR_EREINIT;
+ }
+
+ if (keyPrefix || certPrefix || secmod) {
+ s = NSS_Initialize(dir, certPrefix, keyPrefix, secmod, flags);
+ }
+ else if (dir) {
+ s = NSS_InitReadWrite(dir);
+ }
+ else {
+ s = NSS_NoDB_Init(NULL);
+ }
+ if (s != SECSuccess) {
+ if (result) {
+ /* Note: all memory must be owned by the caller, in case we're unloaded */
+ apu_err_t *err = apr_pcalloc(pool, sizeof(apu_err_t));
+ err->rc = PR_GetError();
+ err->msg = apr_pstrdup(pool, PR_ErrorToName(s));
+ err->reason = apr_pstrdup(pool, "Error during 'nss' initialisation");
+ *result = err;
+ }
+
+ return APR_ECRYPT;
+ }
+
+ apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper,
+ apr_pool_cleanup_null);
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param f The context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+static apr_status_t crypto_block_cleanup(apr_crypto_block_t *block)
+{
+
+ if (block->secParam) {
+ SECITEM_FreeItem(block->secParam, PR_TRUE);
+ block->secParam = NULL;
+ }
+
+ if (block->ctx) {
+ PK11_DestroyContext(block->ctx, PR_TRUE);
+ block->ctx = NULL;
+ }
+
+ return APR_SUCCESS;
+
+}
+
+static apr_status_t crypto_block_cleanup_helper(void *data)
+{
+ apr_crypto_block_t *block = (apr_crypto_block_t *) data;
+ return crypto_block_cleanup(block);
+}
+
+static apr_status_t crypto_key_cleanup(void *data)
+{
+ apr_crypto_key_t *key = data;
+ if (key->symKey) {
+ PK11_FreeSymKey(key->symKey);
+ key->symKey = NULL;
+ }
+ return APR_SUCCESS;
+}
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param f The context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+static apr_status_t crypto_cleanup(apr_crypto_t *f)
+{
+ return APR_SUCCESS;
+}
+
+static apr_status_t crypto_cleanup_helper(void *data)
+{
+ apr_crypto_t *f = (apr_crypto_t *) data;
+ return crypto_cleanup(f);
+}
+
+/**
+ * @brief Create a context for supporting encryption. Keys, certificates,
+ * algorithms and other parameters will be set per context. More than
+ * one context can be created at one time. A cleanup will be automatically
+ * registered with the given pool to guarantee a graceful shutdown.
+ * @param f - context pointer will be written here
+ * @param provider - provider to use
+ * @param params - parameter string
+ * @param pool - process pool
+ * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
+ * if the engine cannot be initialised.
+ */
+static apr_status_t crypto_make(apr_crypto_t **ff,
+ const apr_crypto_driver_t *provider, const char *params,
+ apr_pool_t *pool)
+{
+ apr_crypto_config_t *config = NULL;
+ apr_crypto_t *f;
+
+ f = apr_pcalloc(pool, sizeof(apr_crypto_t));
+ if (!f) {
+ return APR_ENOMEM;
+ }
+ *ff = f;
+ f->pool = pool;
+ f->provider = provider;
+ config = f->config = apr_pcalloc(pool, sizeof(apr_crypto_config_t));
+ if (!config) {
+ return APR_ENOMEM;
+ }
+ f->result = apr_pcalloc(pool, sizeof(apu_err_t));
+ if (!f->result) {
+ return APR_ENOMEM;
+ }
+
+ f->types = apr_hash_make(pool);
+ if (!f->types) {
+ return APR_ENOMEM;
+ }
+ apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0]));
+ apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1]));
+ apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_types[2]));
+ apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_types[3]));
+
+ f->modes = apr_hash_make(pool);
+ if (!f->modes) {
+ return APR_ENOMEM;
+ }
+ apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0]));
+ apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1]));
+
+ apr_pool_cleanup_register(pool, f, crypto_cleanup_helper,
+ apr_pool_cleanup_null);
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Get a hash table of key types, keyed by the name of the type against
+ * a pointer to apr_crypto_block_key_type_t.
+ *
+ * @param types - hashtable of key types keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+static apr_status_t crypto_get_block_key_types(apr_hash_t **types,
+ const apr_crypto_t *f)
+{
+ *types = f->types;
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Get a hash table of key modes, keyed by the name of the mode against
+ * a pointer to apr_crypto_block_key_mode_t.
+ *
+ * @param modes - hashtable of key modes keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+static apr_status_t crypto_get_block_key_modes(apr_hash_t **modes,
+ const apr_crypto_t *f)
+{
+ *modes = f->modes;
+ return APR_SUCCESS;
+}
+
+/*
+ * Work out which mechanism to use.
+ */
+static apr_status_t crypto_cipher_mechanism(apr_crypto_key_t *key,
+ const apr_crypto_block_key_type_e type,
+ const apr_crypto_block_key_mode_e mode, const int doPad)
+{
+
+ /* decide on what cipher mechanism we will be using */
+ switch (type) {
+
+ case (APR_KEY_3DES_192):
+ if (APR_MODE_CBC == mode) {
+ key->cipherOid = SEC_OID_DES_EDE3_CBC;
+ }
+ else if (APR_MODE_ECB == mode) {
+ return APR_ENOCIPHER;
+ /* No OID for CKM_DES3_ECB; */
+ }
+ key->keyLength = 24;
+ break;
+ case (APR_KEY_AES_128):
+ if (APR_MODE_CBC == mode) {
+ key->cipherOid = SEC_OID_AES_128_CBC;
+ }
+ else {
+ key->cipherOid = SEC_OID_AES_128_ECB;
+ }
+ key->keyLength = 16;
+ break;
+ case (APR_KEY_AES_192):
+ if (APR_MODE_CBC == mode) {
+ key->cipherOid = SEC_OID_AES_192_CBC;
+ }
+ else {
+ key->cipherOid = SEC_OID_AES_192_ECB;
+ }
+ key->keyLength = 24;
+ break;
+ case (APR_KEY_AES_256):
+ if (APR_MODE_CBC == mode) {
+ key->cipherOid = SEC_OID_AES_256_CBC;
+ }
+ else {
+ key->cipherOid = SEC_OID_AES_256_ECB;
+ }
+ key->keyLength = 32;
+ break;
+ default:
+ /* unknown key type, give up */
+ return APR_EKEYTYPE;
+ }
+
+ /* AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD */
+ key->cipherMech = PK11_AlgtagToMechanism(key->cipherOid);
+ if (key->cipherMech == CKM_INVALID_MECHANISM) {
+ return APR_ENOCIPHER;
+ }
+ if (doPad) {
+ CK_MECHANISM_TYPE paddedMech;
+ paddedMech = PK11_GetPadMechanism(key->cipherMech);
+ if (CKM_INVALID_MECHANISM == paddedMech
+ || key->cipherMech == paddedMech) {
+ return APR_EPADDING;
+ }
+ key->cipherMech = paddedMech;
+ }
+
+ key->ivSize = PK11_GetIVLength(key->cipherMech);
+
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ * up when the context is cleaned, and may be reused with multiple encryption
+ * or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_key(apr_crypto_key_t **k,
+ const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
+{
+ apr_status_t rv = APR_SUCCESS;
+ PK11SlotInfo *slot, *tslot;
+ PK11SymKey *tkey;
+ SECItem secretItem;
+ SECItem wrappedItem;
+ SECItem *secParam;
+ PK11Context *ctx;
+ SECStatus s;
+ SECItem passItem;
+ SECItem saltItem;
+ SECAlgorithmID *algid;
+ void *wincx = NULL; /* what is wincx? */
+ apr_crypto_key_t *key;
+ int blockSize;
+ int remainder;
+
+ key = *k;
+ if (!key) {
+ *k = key = apr_pcalloc(p, sizeof *key);
+ if (!key) {
+ return APR_ENOMEM;
+ }
+ apr_pool_cleanup_register(p, key, crypto_key_cleanup,
+ apr_pool_cleanup_null);
+ }
+
+ key->f = f;
+ key->provider = f->provider;
+
+ /* decide on what cipher mechanism we will be using */
+ rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad);
+ if (APR_SUCCESS != rv) {
+ return rv;
+ }
+
+ switch (rec->ktype) {
+
+ case APR_CRYPTO_KTYPE_PASSPHRASE: {
+
+ /* Turn the raw passphrase and salt into SECItems */
+ passItem.data = (unsigned char*) rec->k.passphrase.pass;
+ passItem.len = rec->k.passphrase.passLen;
+ saltItem.data = (unsigned char*) rec->k.passphrase.salt;
+ saltItem.len = rec->k.passphrase.saltLen;
+
+ /* generate the key */
+ /* pbeAlg and cipherAlg are the same. */
+ algid = PK11_CreatePBEV2AlgorithmID(key->cipherOid, key->cipherOid,
+ SEC_OID_HMAC_SHA1, key->keyLength,
+ rec->k.passphrase.iterations, &saltItem);
+ if (algid) {
+ slot = PK11_GetBestSlot(key->cipherMech, wincx);
+ if (slot) {
+ key->symKey = PK11_PBEKeyGen(slot, algid, &passItem, PR_FALSE,
+ wincx);
+ PK11_FreeSlot(slot);
+ }
+ SECOID_DestroyAlgorithmID(algid, PR_TRUE);
+ }
+
+ break;
+ }
+
+ case APR_CRYPTO_KTYPE_SECRET: {
+
+ /*
+ * NSS is by default in FIPS mode, which disallows the use of unencrypted
+ * symmetrical keys. As per http://permalink.gmane.org/gmane.comp.mozilla.crypto/7947
+ * we do the following:
+ *
+ * 1. Generate a (temporary) symmetric key in NSS.
+ * 2. Use that symmetric key to encrypt your symmetric key as data.
+ * 3. Unwrap your wrapped symmetric key, using the symmetric key
+ * you generated in Step 1 as the unwrapping key.
+ *
+ * http://permalink.gmane.org/gmane.comp.mozilla.crypto/7947
+ */
+
+ /* generate the key */
+ slot = PK11_GetBestSlot(key->cipherMech, NULL);
+ if (slot) {
+ unsigned char data[BUFFER_SIZE];
+
+ /* sanity check - key correct size? */
+ if (rec->k.secret.secretLen != key->keyLength) {
+ PK11_FreeSlot(slot);
+ return APR_EKEYLENGTH;
+ }
+
+ tslot = PK11_GetBestSlot(CKM_AES_ECB, NULL);
+ if (tslot) {
+
+ /* generate a temporary wrapping key */
+ tkey = PK11_KeyGen(tslot, CKM_AES_ECB, 0, PK11_GetBestKeyLength(tslot, CKM_AES_ECB), 0);
+
+ /* prepare the key to wrap */
+ secretItem.data = (unsigned char *) rec->k.secret.secret;
+ secretItem.len = rec->k.secret.secretLen;
+
+ /* ensure our key matches the blocksize */
+ secParam = PK11_GenerateNewParam(CKM_AES_ECB, tkey);
+ blockSize = PK11_GetBlockSize(CKM_AES_ECB, secParam);
+ remainder = rec->k.secret.secretLen % blockSize;
+ if (remainder) {
+ secretItem.data =
+ apr_pcalloc(p, rec->k.secret.secretLen + remainder);
+ apr_crypto_clear(p, secretItem.data,
+ rec->k.secret.secretLen);
+ memcpy(secretItem.data, rec->k.secret.secret,
+ rec->k.secret.secretLen);
+ secretItem.len += remainder;
+ }
+
+ /* prepare a space for the wrapped key */
+ wrappedItem.data = data;
+
+ /* wrap the key */
+ ctx = PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, tkey,
+ secParam);
+ if (ctx) {
+ s = PK11_CipherOp(ctx, wrappedItem.data,
+ (int *) (&wrappedItem.len), BUFFER_SIZE,
+ secretItem.data, secretItem.len);
+ if (s == SECSuccess) {
+
+ /* unwrap the key again */
+ key->symKey = PK11_UnwrapSymKeyWithFlags(tkey,
+ CKM_AES_ECB, NULL, &wrappedItem,
+ key->cipherMech, CKA_ENCRYPT,
+ rec->k.secret.secretLen, 0);
+
+ }
+
+ PK11_DestroyContext(ctx, PR_TRUE);
+ }
+
+ /* clean up */
+ SECITEM_FreeItem(secParam, PR_TRUE);
+ PK11_FreeSymKey(tkey);
+ PK11_FreeSlot(tslot);
+
+ }
+
+ PK11_FreeSlot(slot);
+ }
+
+ break;
+ }
+
+ default: {
+
+ return APR_ENOKEY;
+
+ }
+ }
+
+ /* sanity check? */
+ if (!key->symKey) {
+ PRErrorCode perr = PORT_GetError();
+ if (perr) {
+ f->result->rc = perr;
+ f->result->msg = PR_ErrorToName(perr);
+ rv = APR_ENOKEY;
+ }
+ }
+
+ return rv;
+}
+
+/**
+ * @brief Create a key from the given passphrase. By default, the PBKDF2
+ * algorithm is used to generate the key from the passphrase. It is expected
+ * that the same pass phrase will generate the same key, regardless of the
+ * backend crypto platform used. The key is cleaned up when the context
+ * is cleaned, and may be reused with multiple encryption or decryption
+ * operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param ivSize The size of the initialisation vector will be returned, based
+ * on whether an IV is relevant for this type of crypto.
+ * @param pass The passphrase to use.
+ * @param passLen The passphrase length in bytes
+ * @param salt The salt to use.
+ * @param saltLen The salt length in bytes
+ * @param type 3DES_192, AES_128, AES_192, AES_256.
+ * @param mode Electronic Code Book / Cipher Block Chaining.
+ * @param doPad Pad if necessary.
+ * @param iterations Iteration count
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
+ const char *pass, apr_size_t passLen, const unsigned char * salt,
+ apr_size_t saltLen, const apr_crypto_block_key_type_e type,
+ const apr_crypto_block_key_mode_e mode, const int doPad,
+ const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+{
+ apr_status_t rv = APR_SUCCESS;
+ PK11SlotInfo * slot;
+ SECItem passItem;
+ SECItem saltItem;
+ SECAlgorithmID *algid;
+ void *wincx = NULL; /* what is wincx? */
+ apr_crypto_key_t *key = *k;
+
+ if (!key) {
+ *k = key = apr_pcalloc(p, sizeof *key);
+ if (!key) {
+ return APR_ENOMEM;
+ }
+ apr_pool_cleanup_register(p, key, crypto_key_cleanup,
+ apr_pool_cleanup_null);
+ }
+
+ key->f = f;
+ key->provider = f->provider;
+
+ /* decide on what cipher mechanism we will be using */
+ rv = crypto_cipher_mechanism(key, type, mode, doPad);
+ if (APR_SUCCESS != rv) {
+ return rv;
+ }
+
+ /* Turn the raw passphrase and salt into SECItems */
+ passItem.data = (unsigned char*) pass;
+ passItem.len = passLen;
+ saltItem.data = (unsigned char*) salt;
+ saltItem.len = saltLen;
+
+ /* generate the key */
+ /* pbeAlg and cipherAlg are the same. */
+ algid = PK11_CreatePBEV2AlgorithmID(key->cipherOid, key->cipherOid,
+ SEC_OID_HMAC_SHA1, key->keyLength, iterations, &saltItem);
+ if (algid) {
+ slot = PK11_GetBestSlot(key->cipherMech, wincx);
+ if (slot) {
+ key->symKey = PK11_PBEKeyGen(slot, algid, &passItem, PR_FALSE,
+ wincx);
+ PK11_FreeSlot(slot);
+ }
+ SECOID_DestroyAlgorithmID(algid, PR_TRUE);
+ }
+
+ /* sanity check? */
+ if (!key->symKey) {
+ PRErrorCode perr = PORT_GetError();
+ if (perr) {
+ f->result->rc = perr;
+ f->result->msg = PR_ErrorToName(perr);
+ rv = APR_ENOKEY;
+ }
+ }
+
+ if (ivSize) {
+ *ivSize = key->ivSize;
+ }
+
+ return rv;
+}
+
+/**
+ * @brief Initialise a context for encrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ * *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ * an IV will be created at random, in space allocated from the pool.
+ * If the buffer pointed to is not NULL, the IV in the buffer will be
+ * used.
+ * @param key The key structure.
+ * @param blockSize The block size of the cipher.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ * Returns APR_EINIT if the backend failed to initialise the context. Returns
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
+ const unsigned char **iv, const apr_crypto_key_t *key,
+ apr_size_t *blockSize, apr_pool_t *p)
+{
+ PRErrorCode perr;
+ SECItem ivItem;
+ unsigned char * usedIv;
+ apr_crypto_block_t *block = *ctx;
+ if (!block) {
+ *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
+ }
+ if (!block) {
+ return APR_ENOMEM;
+ }
+ block->f = key->f;
+ block->pool = p;
+ block->provider = key->provider;
+
+ apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
+ apr_pool_cleanup_null);
+
+ if (key->ivSize) {
+ if (iv == NULL) {
+ return APR_ENOIV;
+ }
+ if (*iv == NULL) {
+ SECStatus s;
+ usedIv = apr_pcalloc(p, key->ivSize);
+ if (!usedIv) {
+ return APR_ENOMEM;
+ }
+ apr_crypto_clear(p, usedIv, key->ivSize);
+ s = PK11_GenerateRandom(usedIv, key->ivSize);
+ if (s != SECSuccess) {
+ return APR_ENOIV;
+ }
+ *iv = usedIv;
+ }
+ else {
+ usedIv = (unsigned char *) *iv;
+ }
+ ivItem.data = usedIv;
+ ivItem.len = key->ivSize;
+ block->secParam = PK11_ParamFromIV(key->cipherMech, &ivItem);
+ }
+ else {
+ block->secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey);
+ }
+ block->blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
+ block->ctx = PK11_CreateContextBySymKey(key->cipherMech, CKA_ENCRYPT,
+ key->symKey, block->secParam);
+
+ /* did an error occur? */
+ perr = PORT_GetError();
+ if (perr || !block->ctx) {
+ key->f->result->rc = perr;
+ key->f->result->msg = PR_ErrorToName(perr);
+ return APR_EINIT;
+ }
+
+ if (blockSize) {
+ *blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
+ }
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Encrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ * out is NULL, outlen will contain the maximum size of the
+ * buffer needed to hold the data, including any data
+ * generated by apr_crypto_block_encrypt_finish below. If *out points
+ * to NULL, a buffer sufficiently large will be created from
+ * the pool provided. If *out points to a not-NULL value, this
+ * value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ * see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ * not implemented.
+ */
+static apr_status_t crypto_block_encrypt(unsigned char **out,
+ apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+ apr_crypto_block_t *block)
+{
+
+ unsigned char *buffer;
+ int outl = (int) *outlen;
+ SECStatus s;
+ if (!out) {
+ *outlen = inlen + block->blockSize;
+ return APR_SUCCESS;
+ }
+ if (!*out) {
+ buffer = apr_palloc(block->pool, inlen + block->blockSize);
+ if (!buffer) {
+ return APR_ENOMEM;
+ }
+ apr_crypto_clear(block->pool, buffer, inlen + block->blockSize);
+ *out = buffer;
+ }
+
+ s = PK11_CipherOp(block->ctx, *out, &outl, inlen, (unsigned char*) in,
+ inlen);
+ if (s != SECSuccess) {
+ PRErrorCode perr = PORT_GetError();
+ if (perr) {
+ block->f->result->rc = perr;
+ block->f->result->msg = PR_ErrorToName(perr);
+ }
+ return APR_ECRYPT;
+ }
+ *outlen = outl;
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Encrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ * padded. Typically the final block will be written to the
+ * same buffer used by apr_crypto_block_encrypt, offset by the
+ * number of bytes returned as actually written by the
+ * apr_crypto_block_encrypt() call. After this call, the context
+ * is cleaned and can be reused by apr_crypto_block_encrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ * buffer must already exist, and is usually the same
+ * buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ * formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_encrypt_finish(unsigned char *out,
+ apr_size_t *outlen, apr_crypto_block_t *block)
+{
+
+ apr_status_t rv = APR_SUCCESS;
+ unsigned int outl = *outlen;
+
+ SECStatus s = PK11_DigestFinal(block->ctx, out, &outl, block->blockSize);
+ *outlen = outl;
+
+ if (s != SECSuccess) {
+ PRErrorCode perr = PORT_GetError();
+ if (perr) {
+ block->f->result->rc = perr;
+ block->f->result->msg = PR_ErrorToName(perr);
+ }
+ rv = APR_ECRYPT;
+ }
+ crypto_block_cleanup(block);
+
+ return rv;
+
+}
+
+/**
+ * @brief Initialise a context for decrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ * *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param blockSize The block size of the cipher.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ * an IV will be created at random, in space allocated from the pool.
+ * If the buffer is not NULL, the IV in the buffer will be used.
+ * @param key The key structure.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ * Returns APR_EINIT if the backend failed to initialise the context. Returns
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
+ apr_size_t *blockSize, const unsigned char *iv,
+ const apr_crypto_key_t *key, apr_pool_t *p)
+{
+ PRErrorCode perr;
+ apr_crypto_block_t *block = *ctx;
+ if (!block) {
+ *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
+ }
+ if (!block) {
+ return APR_ENOMEM;
+ }
+ block->f = key->f;
+ block->pool = p;
+ block->provider = key->provider;
+
+ apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
+ apr_pool_cleanup_null);
+
+ if (key->ivSize) {
+ SECItem ivItem;
+ if (iv == NULL) {
+ return APR_ENOIV; /* Cannot initialise without an IV */
+ }
+ ivItem.data = (unsigned char*) iv;
+ ivItem.len = key->ivSize;
+ block->secParam = PK11_ParamFromIV(key->cipherMech, &ivItem);
+ }
+ else {
+ block->secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey);
+ }
+ block->blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
+ block->ctx = PK11_CreateContextBySymKey(key->cipherMech, CKA_DECRYPT,
+ key->symKey, block->secParam);
+
+ /* did an error occur? */
+ perr = PORT_GetError();
+ if (perr || !block->ctx) {
+ key->f->result->rc = perr;
+ key->f->result->msg = PR_ErrorToName(perr);
+ return APR_EINIT;
+ }
+
+ if (blockSize) {
+ *blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
+ }
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Decrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ * out is NULL, outlen will contain the maximum size of the
+ * buffer needed to hold the data, including any data
+ * generated by apr_crypto_block_decrypt_finish below. If *out points
+ * to NULL, a buffer sufficiently large will be created from
+ * the pool provided. If *out points to a not-NULL value, this
+ * value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ * see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ * not implemented.
+ */
+static apr_status_t crypto_block_decrypt(unsigned char **out,
+ apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+ apr_crypto_block_t *block)
+{
+
+ unsigned char *buffer;
+ int outl = (int) *outlen;
+ SECStatus s;
+ if (!out) {
+ *outlen = inlen + block->blockSize;
+ return APR_SUCCESS;
+ }
+ if (!*out) {
+ buffer = apr_palloc(block->pool, inlen + block->blockSize);
+ if (!buffer) {
+ return APR_ENOMEM;
+ }
+ apr_crypto_clear(block->pool, buffer, inlen + block->blockSize);
+ *out = buffer;
+ }
+
+ s = PK11_CipherOp(block->ctx, *out, &outl, inlen, (unsigned char*) in,
+ inlen);
+ if (s != SECSuccess) {
+ PRErrorCode perr = PORT_GetError();
+ if (perr) {
+ block->f->result->rc = perr;
+ block->f->result->msg = PR_ErrorToName(perr);
+ }
+ return APR_ECRYPT;
+ }
+ *outlen = outl;
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Decrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ * padded. Typically the final block will be written to the
+ * same buffer used by apr_crypto_block_decrypt, offset by the
+ * number of bytes returned as actually written by the
+ * apr_crypto_block_decrypt() call. After this call, the context
+ * is cleaned and can be reused by apr_crypto_block_decrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ * buffer must already exist, and is usually the same
+ * buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ * formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_decrypt_finish(unsigned char *out,
+ apr_size_t *outlen, apr_crypto_block_t *block)
+{
+
+ apr_status_t rv = APR_SUCCESS;
+ unsigned int outl = *outlen;
+
+ SECStatus s = PK11_DigestFinal(block->ctx, out, &outl, block->blockSize);
+ *outlen = outl;
+
+ if (s != SECSuccess) {
+ PRErrorCode perr = PORT_GetError();
+ if (perr) {
+ block->f->result->rc = perr;
+ block->f->result->msg = PR_ErrorToName(perr);
+ }
+ rv = APR_ECRYPT;
+ }
+ crypto_block_cleanup(block);
+
+ return rv;
+
+}
+
+/**
+ * NSS module.
+ */
+APU_MODULE_DECLARE_DATA const apr_crypto_driver_t apr_crypto_nss_driver = {
+ "nss", crypto_init, crypto_make, crypto_get_block_key_types,
+ crypto_get_block_key_modes, crypto_passphrase,
+ crypto_block_encrypt_init, crypto_block_encrypt,
+ crypto_block_encrypt_finish, crypto_block_decrypt_init,
+ crypto_block_decrypt, crypto_block_decrypt_finish,
+ crypto_block_cleanup, crypto_cleanup, crypto_shutdown, crypto_error,
+ crypto_key
+};
+
+#endif
diff --git a/crypto/apr_crypto_nss.dep b/crypto/apr_crypto_nss.dep
new file mode 100644
index 0000000..94fb8bd
--- /dev/null
+++ b/crypto/apr_crypto_nss.dep
@@ -0,0 +1,15 @@
+# Microsoft Developer Studio Generated Dependency File, included by apr_crypto_nss.mak
+
+.\apr_crypto_nss.c : \
+ "..\include\apr_buckets.h"\
+ "..\include\apr_crypto.h"\
+ "..\include\apu.h"\
+ "..\include\apu_errno.h"\
+ "..\include\private\apr_crypto_internal.h"\
+ "..\include\private\apu_config.h"\
+
+
+..\libaprutil.rc : \
+ "..\include\apu.h"\
+ "..\include\apu_version.h"\
+
diff --git a/crypto/apr_crypto_nss.dsp b/crypto/apr_crypto_nss.dsp
new file mode 100644
index 0000000..43d0a56
--- /dev/null
+++ b/crypto/apr_crypto_nss.dsp
@@ -0,0 +1,203 @@
+# Microsoft Developer Studio Project File - Name="apr_crypto_nss" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=apr_crypto_nss - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "apr_crypto_nss.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "apr_crypto_nss.mak" CFG="apr_crypto_nss - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "apr_crypto_nss - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_nss - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_nss - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_nss - x64 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "apr_crypto_nss - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../../apr/include" /I "../include/private" /I "../../nss/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_NSS=1 /D HAVE_NSS_H=1 /D HAVE_PK11PUB_H=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_crypto_nss_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/apr_crypto_nss-1.res" /d DLL_NAME="apr_crypto_nss" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib libnspr4.lib /nologo /libpath:..\..\nss\lib /base:"0x6F110000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib libnspr4.lib /nologo /libpath:..\..\nss\lib /base:"0x6F110000" /subsystem:windows /dll /incremental:no /debug /out:"Release\apr_crypto_nss-1.dll" /pdb:"Release\apr_crypto_nss-1.pdb" /implib:"Release\apr_crypto_nss-1.lib" /MACHINE:X86 /opt:ref
+# Begin Special Build Tool
+TargetPath=Release\apr_crypto_nss-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "apr_crypto_nss - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../../apr/include" /I "../include/private" /I "../../nss/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_NSS=1 /D HAVE_NSS_H=1 /D HAVE_PK11PUB_H=1 /D /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_crypto_nss_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/apr_crypto_nss-1.res" /d DLL_NAME="apr_crypto_nss" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib libnspr4.lib /nologo /libpath:..\..\nss\lib /base:"0x6F110000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib libnspr4.lib /nologo /libpath:..\..\nss\lib /base:"0x6F110000" /subsystem:windows /dll /incremental:no /debug /out:"Debug\apr_crypto_nss-1.dll" /pdb:"Debug\apr_crypto_nss-1.pdb" /implib:"Debug\apr_crypto_nss-1.lib" /MACHINE:X86
+# Begin Special Build Tool
+TargetPath=Debug\apr_crypto_nss-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "apr_crypto_nss - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "WIN64" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../../apr/include" /I "../include/private" /I "../../nss/include" /D "NDEBUG" /D "WIN32" /D "WIN64" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_NSS=1 /D HAVE_NSS_H=1 /D HAVE_PK11PUB_H=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_crypto_nss_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /x64 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /x64 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"x64\Release/apr_crypto_nss-1.res" /d DLL_NAME="apr_crypto_nss" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib libnspr4.lib /nologo /libpath:..\..\nss\lib /base:"0x6F110000" /subsystem:windows /machine:X64 /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib libnspr4.lib /nologo /libpath:..\..\nss\lib /base:"0x6F110000" /subsystem:windows /machine:X64 /dll /incremental:no /debug /out:"x64\Release\apr_crypto_nss-1.dll" /pdb:"x64\Release\apr_crypto_nss-1.pdb" /implib:"x64\Release\apr_crypto_nss-1.lib" /opt:ref
+# Begin Special Build Tool
+TargetPath=x64\Release\apr_crypto_nss-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "apr_crypto_nss - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\Debug"
+# PROP Intermediate_Dir "x64\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "WIN64" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../../apr/include" /I "../include/private" /I "../../nss/include" /D "_DEBUG" /D "WIN32" /D "WIN64" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_NSS=1 /D HAVE_NSS_H=1 /D HAVE_PK11PUB_H=1 /D /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_crypto_nss_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /x64 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /x64 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"x64\Debug/apr_crypto_nss-1.res" /d DLL_NAME="apr_crypto_nss" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib libnspr4.lib /nologo /libpath:..\..\nss\lib /base:"0x6F110000" /subsystem:windows /machine:X64 /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib libnspr4.lib /nologo /libpath:..\..\nss\lib /base:"0x6F110000" /subsystem:windows /machine:X64 /dll /incremental:no /debug /out:"x64\Debug\apr_crypto_nss-1.dll" /pdb:"x64\Debug\apr_crypto_nss-1.pdb" /implib:"x64\Debug\apr_crypto_nss-1.lib"
+# Begin Special Build Tool
+TargetPath=x64\Debug\apr_crypto_nss-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "apr_crypto_nss - Win32 Release"
+# Name "apr_crypto_nss - Win32 Debug"
+# Name "apr_crypto_nss - x64 Release"
+# Name "apr_crypto_nss - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\apr_crypto_nss.c
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\apr_crypto.h
+# End Source File
+# End Group
+# Begin Group "Internal Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\private\apu_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_internal.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\libaprutil.rc
+# End Source File
+# End Target
+# End Project
diff --git a/crypto/apr_crypto_nss.mak b/crypto/apr_crypto_nss.mak
new file mode 100644
index 0000000..626ee30
--- /dev/null
+++ b/crypto/apr_crypto_nss.mak
@@ -0,0 +1,594 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on apr_crypto_nss.dsp
+!IF "$(CFG)" == ""
+CFG=apr_crypto_nss - Win32 Release
+!MESSAGE No configuration specified. Defaulting to apr_crypto_nss - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "apr_crypto_nss - Win32 Release" && "$(CFG)" != "apr_crypto_nss - Win32 Debug" && "$(CFG)" != "apr_crypto_nss - x64 Release" && "$(CFG)" != "apr_crypto_nss - x64 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "apr_crypto_nss.mak" CFG="apr_crypto_nss - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "apr_crypto_nss - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_nss - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_nss - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_nss - x64 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "apr_crypto_nss - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\apr_crypto_nss-1.dll" "$(DS_POSTBUILD_DEP)"
+
+!ELSE
+
+ALL : "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\apr_crypto_nss-1.dll" "$(DS_POSTBUILD_DEP)"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\apr_crypto_nss-1.res"
+ -@erase "$(INTDIR)\apr_crypto_nss.obj"
+ -@erase "$(INTDIR)\apr_crypto_nss_src.idb"
+ -@erase "$(INTDIR)\apr_crypto_nss_src.pdb"
+ -@erase "$(OUTDIR)\apr_crypto_nss-1.dll"
+ -@erase "$(OUTDIR)\apr_crypto_nss-1.exp"
+ -@erase "$(OUTDIR)\apr_crypto_nss-1.lib"
+ -@erase "$(OUTDIR)\apr_crypto_nss-1.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../../apr/include" /I "../include/private" /I "../../nss/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_NSS=1 /D HAVE_NSS_H=1 /D HAVE_PK11PUB_H=1 /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\apr_crypto_nss_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\apr_crypto_nss-1.res" /i "../include" /i "../../apr/include" /d DLL_NAME="apr_crypto_nss" /d "NDEBUG" /d "APU_VERSION_ONLY"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\apr_crypto_nss.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib libnspr4.lib /nologo /base:"0x6F110000" /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\apr_crypto_nss-1.pdb" /debug /out:"$(OUTDIR)\apr_crypto_nss-1.dll" /implib:"$(OUTDIR)\apr_crypto_nss-1.lib" /libpath:"..\..\nss\lib" /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\apr_crypto_nss.obj" \
+ "$(INTDIR)\apr_crypto_nss-1.res" \
+ "..\..\apr\Release\libapr-1.lib" \
+ "..\Release\libaprutil-1.lib"
+
+"$(OUTDIR)\apr_crypto_nss-1.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+TargetPath=.\Release\apr_crypto_nss-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\apr_crypto_nss-1.dll"
+ if exist .\Release\apr_crypto_nss-1.dll.manifest mt.exe -manifest .\Release\apr_crypto_nss-1.dll.manifest -outputresource:.\Release\apr_crypto_nss-1.dll;2
+ echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
+
+!ELSEIF "$(CFG)" == "apr_crypto_nss - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\apr_crypto_nss-1.dll" "$(DS_POSTBUILD_DEP)"
+
+!ELSE
+
+ALL : "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\apr_crypto_nss-1.dll" "$(DS_POSTBUILD_DEP)"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\apr_crypto_nss-1.res"
+ -@erase "$(INTDIR)\apr_crypto_nss.obj"
+ -@erase "$(INTDIR)\apr_crypto_nss_src.idb"
+ -@erase "$(INTDIR)\apr_crypto_nss_src.pdb"
+ -@erase "$(OUTDIR)\apr_crypto_nss-1.dll"
+ -@erase "$(OUTDIR)\apr_crypto_nss-1.exp"
+ -@erase "$(OUTDIR)\apr_crypto_nss-1.lib"
+ -@erase "$(OUTDIR)\apr_crypto_nss-1.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../include" /I "../../apr/include" /I "../include/private" /I "../../nss/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_NSS=1 /D HAVE_NSS_H=1 /D HAVE_PK11PUB_H=1 /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\apr_crypto_nss_src" /FD /D /EHsc /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\apr_crypto_nss-1.res" /i "../include" /i "../../apr/include" /d DLL_NAME="apr_crypto_nss" /d "_DEBUG" /d "APU_VERSION_ONLY"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\apr_crypto_nss.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib libnspr4.lib /nologo /base:"0x6F110000" /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\apr_crypto_nss-1.pdb" /debug /out:"$(OUTDIR)\apr_crypto_nss-1.dll" /implib:"$(OUTDIR)\apr_crypto_nss-1.lib" /libpath:"..\..\nss\lib"
+LINK32_OBJS= \
+ "$(INTDIR)\apr_crypto_nss.obj" \
+ "$(INTDIR)\apr_crypto_nss-1.res" \
+ "..\..\apr\Debug\libapr-1.lib" \
+ "..\Debug\libaprutil-1.lib"
+
+"$(OUTDIR)\apr_crypto_nss-1.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+TargetPath=.\Debug\apr_crypto_nss-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\apr_crypto_nss-1.dll"
+ if exist .\Debug\apr_crypto_nss-1.dll.manifest mt.exe -manifest .\Debug\apr_crypto_nss-1.dll.manifest -outputresource:.\Debug\apr_crypto_nss-1.dll;2
+ echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
+
+!ELSEIF "$(CFG)" == "apr_crypto_nss - x64 Release"
+
+OUTDIR=.\x64\Release
+INTDIR=.\x64\Release
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+# Begin Custom Macros
+OutDir=.\x64\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\apr_crypto_nss-1.dll" "$(DS_POSTBUILD_DEP)"
+
+!ELSE
+
+ALL : "libaprutil - x64 Release" "libapr - x64 Release" "$(OUTDIR)\apr_crypto_nss-1.dll" "$(DS_POSTBUILD_DEP)"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libapr - x64 ReleaseCLEAN" "libaprutil - x64 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\apr_crypto_nss-1.res"
+ -@erase "$(INTDIR)\apr_crypto_nss.obj"
+ -@erase "$(INTDIR)\apr_crypto_nss_src.idb"
+ -@erase "$(INTDIR)\apr_crypto_nss_src.pdb"
+ -@erase "$(OUTDIR)\apr_crypto_nss-1.dll"
+ -@erase "$(OUTDIR)\apr_crypto_nss-1.exp"
+ -@erase "$(OUTDIR)\apr_crypto_nss-1.lib"
+ -@erase "$(OUTDIR)\apr_crypto_nss-1.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../../apr/include" /I "../include/private" /I "../../nss/include" /D "NDEBUG" /D "WIN32" /D "WIN64" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_NSS=1 /D HAVE_NSS_H=1 /D HAVE_PK11PUB_H=1 /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\apr_crypto_nss_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /x64 "NUL"
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\apr_crypto_nss-1.res" /i "../include" /i "../../apr/include" /d DLL_NAME="apr_crypto_nss" /d "NDEBUG" /d "APU_VERSION_ONLY"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\apr_crypto_nss.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib libnspr4.lib /nologo /base:"0x6F110000" /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\apr_crypto_nss-1.pdb" /debug /out:"$(OUTDIR)\apr_crypto_nss-1.dll" /implib:"$(OUTDIR)\apr_crypto_nss-1.lib" /libpath:"..\..\nss\lib" /machine:X64 /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\apr_crypto_nss.obj" \
+ "$(INTDIR)\apr_crypto_nss-1.res" \
+ "..\..\apr\x64\Release\libapr-1.lib" \
+ "..\x64\Release\libaprutil-1.lib"
+
+"$(OUTDIR)\apr_crypto_nss-1.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+TargetPath=.\x64\Release\apr_crypto_nss-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+
+# Begin Custom Macros
+OutDir=.\x64\Release
+# End Custom Macros
+
+"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\apr_crypto_nss-1.dll"
+ if exist .\x64\Release\apr_crypto_nss-1.dll.manifest mt.exe -manifest .\x64\Release\apr_crypto_nss-1.dll.manifest -outputresource:.\x64\Release\apr_crypto_nss-1.dll;2
+ echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
+
+!ELSEIF "$(CFG)" == "apr_crypto_nss - x64 Debug"
+
+OUTDIR=.\x64\Debug
+INTDIR=.\x64\Debug
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+# Begin Custom Macros
+OutDir=.\x64\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\apr_crypto_nss-1.dll" "$(DS_POSTBUILD_DEP)"
+
+!ELSE
+
+ALL : "libaprutil - x64 Debug" "libapr - x64 Debug" "$(OUTDIR)\apr_crypto_nss-1.dll" "$(DS_POSTBUILD_DEP)"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libapr - x64 DebugCLEAN" "libaprutil - x64 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\apr_crypto_nss-1.res"
+ -@erase "$(INTDIR)\apr_crypto_nss.obj"
+ -@erase "$(INTDIR)\apr_crypto_nss_src.idb"
+ -@erase "$(INTDIR)\apr_crypto_nss_src.pdb"
+ -@erase "$(OUTDIR)\apr_crypto_nss-1.dll"
+ -@erase "$(OUTDIR)\apr_crypto_nss-1.exp"
+ -@erase "$(OUTDIR)\apr_crypto_nss-1.lib"
+ -@erase "$(OUTDIR)\apr_crypto_nss-1.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../include" /I "../../apr/include" /I "../include/private" /I "../../nss/include" /D "_DEBUG" /D "WIN32" /D "WIN64" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_NSS=1 /D HAVE_NSS_H=1 /D HAVE_PK11PUB_H=1 /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\apr_crypto_nss_src" /FD /D /EHsc /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /x64 "NUL"
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\apr_crypto_nss-1.res" /i "../include" /i "../../apr/include" /d DLL_NAME="apr_crypto_nss" /d "_DEBUG" /d "APU_VERSION_ONLY"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\apr_crypto_nss.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib nss3.lib libnspr4.lib /nologo /base:"0x6F110000" /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\apr_crypto_nss-1.pdb" /debug /out:"$(OUTDIR)\apr_crypto_nss-1.dll" /implib:"$(OUTDIR)\apr_crypto_nss-1.lib" /libpath:"..\..\nss\lib" /machine:X64
+LINK32_OBJS= \
+ "$(INTDIR)\apr_crypto_nss.obj" \
+ "$(INTDIR)\apr_crypto_nss-1.res" \
+ "..\..\apr\x64\Debug\libapr-1.lib" \
+ "..\x64\Debug\libaprutil-1.lib"
+
+"$(OUTDIR)\apr_crypto_nss-1.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+TargetPath=.\x64\Debug\apr_crypto_nss-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+
+# Begin Custom Macros
+OutDir=.\x64\Debug
+# End Custom Macros
+
+"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\apr_crypto_nss-1.dll"
+ if exist .\x64\Debug\apr_crypto_nss-1.dll.manifest mt.exe -manifest .\x64\Debug\apr_crypto_nss-1.dll.manifest -outputresource:.\x64\Debug\apr_crypto_nss-1.dll;2
+ echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("apr_crypto_nss.dep")
+!INCLUDE "apr_crypto_nss.dep"
+!ELSE
+!MESSAGE Warning: cannot find "apr_crypto_nss.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "apr_crypto_nss - Win32 Release" || "$(CFG)" == "apr_crypto_nss - Win32 Debug" || "$(CFG)" == "apr_crypto_nss - x64 Release" || "$(CFG)" == "apr_crypto_nss - x64 Debug"
+SOURCE=.\apr_crypto_nss.c
+
+"$(INTDIR)\apr_crypto_nss.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!IF "$(CFG)" == "apr_crypto_nss - Win32 Release"
+
+"libapr - Win32 Release" :
+ cd ".\..\..\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release"
+ cd "..\apr-util\crypto"
+
+"libapr - Win32 ReleaseCLEAN" :
+ cd ".\..\..\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN
+ cd "..\apr-util\crypto"
+
+!ELSEIF "$(CFG)" == "apr_crypto_nss - Win32 Debug"
+
+"libapr - Win32 Debug" :
+ cd ".\..\..\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug"
+ cd "..\apr-util\crypto"
+
+"libapr - Win32 DebugCLEAN" :
+ cd ".\..\..\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\apr-util\crypto"
+
+!ELSEIF "$(CFG)" == "apr_crypto_nss - x64 Release"
+
+"libapr - x64 Release" :
+ cd ".\..\..\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - x64 Release"
+ cd "..\apr-util\crypto"
+
+"libapr - x64 ReleaseCLEAN" :
+ cd ".\..\..\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - x64 Release" RECURSE=1 CLEAN
+ cd "..\apr-util\crypto"
+
+!ELSEIF "$(CFG)" == "apr_crypto_nss - x64 Debug"
+
+"libapr - x64 Debug" :
+ cd ".\..\..\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - x64 Debug"
+ cd "..\apr-util\crypto"
+
+"libapr - x64 DebugCLEAN" :
+ cd ".\..\..\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - x64 Debug" RECURSE=1 CLEAN
+ cd "..\apr-util\crypto"
+
+!ENDIF
+
+!IF "$(CFG)" == "apr_crypto_nss - Win32 Release"
+
+"libaprutil - Win32 Release" :
+ cd ".\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release"
+ cd ".\crypto"
+
+"libaprutil - Win32 ReleaseCLEAN" :
+ cd ".\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN
+ cd ".\crypto"
+
+!ELSEIF "$(CFG)" == "apr_crypto_nss - Win32 Debug"
+
+"libaprutil - Win32 Debug" :
+ cd ".\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug"
+ cd ".\crypto"
+
+"libaprutil - Win32 DebugCLEAN" :
+ cd ".\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\crypto"
+
+!ELSEIF "$(CFG)" == "apr_crypto_nss - x64 Release"
+
+"libaprutil - x64 Release" :
+ cd ".\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - x64 Release"
+ cd ".\crypto"
+
+"libaprutil - x64 ReleaseCLEAN" :
+ cd ".\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - x64 Release" RECURSE=1 CLEAN
+ cd ".\crypto"
+
+!ELSEIF "$(CFG)" == "apr_crypto_nss - x64 Debug"
+
+"libaprutil - x64 Debug" :
+ cd ".\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - x64 Debug"
+ cd ".\crypto"
+
+"libaprutil - x64 DebugCLEAN" :
+ cd ".\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - x64 Debug" RECURSE=1 CLEAN
+ cd ".\crypto"
+
+!ENDIF
+
+SOURCE=..\libaprutil.rc
+
+!IF "$(CFG)" == "apr_crypto_nss - Win32 Release"
+
+
+"$(INTDIR)\apr_crypto_nss-1.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)\apr_crypto_nss-1.res" /i "../include" /i "../../apr/include" /i "\httpd-2.4.4\srclib\apr-util" /d DLL_NAME="apr_crypto_nss" /d "NDEBUG" /d "APU_VERSION_ONLY" $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "apr_crypto_nss - Win32 Debug"
+
+
+"$(INTDIR)\apr_crypto_nss-1.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)\apr_crypto_nss-1.res" /i "../include" /i "../../apr/include" /i "\httpd-2.4.4\srclib\apr-util" /d DLL_NAME="apr_crypto_nss" /d "_DEBUG" /d "APU_VERSION_ONLY" $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "apr_crypto_nss - x64 Release"
+
+
+"$(INTDIR)\apr_crypto_nss-1.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)\apr_crypto_nss-1.res" /i "../include" /i "../../apr/include" /i "\httpd-2.4.4\srclib\apr-util" /d DLL_NAME="apr_crypto_nss" /d "NDEBUG" /d "APU_VERSION_ONLY" $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "apr_crypto_nss - x64 Debug"
+
+
+"$(INTDIR)\apr_crypto_nss-1.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)\apr_crypto_nss-1.res" /i "../include" /i "../../apr/include" /i "\httpd-2.4.4\srclib\apr-util" /d DLL_NAME="apr_crypto_nss" /d "_DEBUG" /d "APU_VERSION_ONLY" $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
diff --git a/crypto/apr_crypto_openssl.c b/crypto/apr_crypto_openssl.c
new file mode 100644
index 0000000..310bb2c
--- /dev/null
+++ b/crypto/apr_crypto_openssl.c
@@ -0,0 +1,973 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_lib.h"
+#include "apu.h"
+#include "apu_errno.h"
+
+#include <ctype.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "apr_strings.h"
+#include "apr_time.h"
+#include "apr_buckets.h"
+
+#include "apr_crypto_internal.h"
+
+#if APU_HAVE_CRYPTO
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/engine.h>
+
+#define LOG_PREFIX "apr_crypto_openssl: "
+
+#ifndef APR_USE_OPENSSL_PRE_1_1_API
+#if defined(LIBRESSL_VERSION_NUMBER)
+/* LibreSSL declares OPENSSL_VERSION_NUMBER == 2.0 but does not include most
+ * changes from OpenSSL >= 1.1 (new functions, macros, deprecations, ...), so
+ * we have to work around this...
+ */
+#define APR_USE_OPENSSL_PRE_1_1_API (1)
+#else
+#define APR_USE_OPENSSL_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L)
+#endif
+#endif
+
+struct apr_crypto_t {
+ apr_pool_t *pool;
+ const apr_crypto_driver_t *provider;
+ apu_err_t *result;
+ apr_crypto_config_t *config;
+ apr_hash_t *types;
+ apr_hash_t *modes;
+};
+
+struct apr_crypto_config_t {
+ ENGINE *engine;
+};
+
+struct apr_crypto_key_t {
+ apr_pool_t *pool;
+ const apr_crypto_driver_t *provider;
+ const apr_crypto_t *f;
+ const EVP_CIPHER * cipher;
+ unsigned char *key;
+ int keyLen;
+ int doPad;
+ int ivSize;
+};
+
+struct apr_crypto_block_t {
+ apr_pool_t *pool;
+ const apr_crypto_driver_t *provider;
+ const apr_crypto_t *f;
+ EVP_CIPHER_CTX *cipherCtx;
+ int initialised;
+ int ivSize;
+ int blockSize;
+ int doPad;
+};
+
+static struct apr_crypto_block_key_type_t key_types[] =
+{
+{ APR_KEY_3DES_192, 24, 8, 8 },
+{ APR_KEY_AES_128, 16, 16, 16 },
+{ APR_KEY_AES_192, 24, 16, 16 },
+{ APR_KEY_AES_256, 32, 16, 16 } };
+
+static struct apr_crypto_block_key_mode_t key_modes[] =
+{
+{ APR_MODE_ECB },
+{ APR_MODE_CBC } };
+
+/* sufficient space to wrap a key */
+#define BUFFER_SIZE 128
+
+/**
+ * Fetch the most recent error from this driver.
+ */
+static apr_status_t crypto_error(const apu_err_t **result,
+ const apr_crypto_t *f)
+{
+ *result = f->result;
+ return APR_SUCCESS;
+}
+
+/**
+ * Shutdown the crypto library and release resources.
+ */
+static apr_status_t crypto_shutdown(void)
+{
+ ERR_free_strings();
+ EVP_cleanup();
+ ENGINE_cleanup();
+ return APR_SUCCESS;
+}
+
+static apr_status_t crypto_shutdown_helper(void *data)
+{
+ return crypto_shutdown();
+}
+
+/**
+ * Initialise the crypto library and perform one time initialisation.
+ */
+static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
+ const apu_err_t **result)
+{
+#if APR_USE_OPENSSL_PRE_1_1_API
+ (void)CRYPTO_malloc_init();
+#else
+ OPENSSL_malloc_init();
+#endif
+ ERR_load_crypto_strings();
+ /* SSL_load_error_strings(); */
+ OpenSSL_add_all_algorithms();
+ ENGINE_load_builtin_engines();
+ ENGINE_register_all_complete();
+
+ apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper,
+ apr_pool_cleanup_null);
+
+ return APR_SUCCESS;
+}
+
+#if OPENSSL_VERSION_NUMBER < 0x0090802fL
+
+/* Code taken from OpenSSL 0.9.8b, see
+ * https://github.com/openssl/openssl/commit/cf6bc84148cb15af09b292394aaf2b45f0d5af0d
+ */
+
+EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void)
+{
+ EVP_CIPHER_CTX *ctx = OPENSSL_malloc(sizeof *ctx);
+ if (ctx)
+ EVP_CIPHER_CTX_init(ctx);
+ return ctx;
+}
+
+void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
+{
+ if (ctx) {
+ EVP_CIPHER_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+#endif
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param ctx The block context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+static apr_status_t crypto_block_cleanup(apr_crypto_block_t *ctx)
+{
+
+ if (ctx->initialised) {
+ EVP_CIPHER_CTX_free(ctx->cipherCtx);
+ ctx->initialised = 0;
+ }
+
+ return APR_SUCCESS;
+
+}
+
+static apr_status_t crypto_block_cleanup_helper(void *data)
+{
+ apr_crypto_block_t *block = (apr_crypto_block_t *) data;
+ return crypto_block_cleanup(block);
+}
+
+/**
+ * @brief Clean encryption / decryption context.
+ * @note After cleanup, a context is free to be reused if necessary.
+ * @param f The context to use.
+ * @return Returns APR_ENOTIMPL if not supported.
+ */
+static apr_status_t crypto_cleanup(apr_crypto_t *f)
+{
+
+ if (f->config->engine) {
+ ENGINE_finish(f->config->engine);
+ ENGINE_free(f->config->engine);
+ f->config->engine = NULL;
+ }
+ return APR_SUCCESS;
+
+}
+
+static apr_status_t crypto_cleanup_helper(void *data)
+{
+ apr_crypto_t *f = (apr_crypto_t *) data;
+ return crypto_cleanup(f);
+}
+
+/**
+ * @brief Create a context for supporting encryption. Keys, certificates,
+ * algorithms and other parameters will be set per context. More than
+ * one context can be created at one time. A cleanup will be automatically
+ * registered with the given pool to guarantee a graceful shutdown.
+ * @param f - context pointer will be written here
+ * @param provider - provider to use
+ * @param params - array of key parameters
+ * @param pool - process pool
+ * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
+ * if the engine cannot be initialised.
+ */
+static apr_status_t crypto_make(apr_crypto_t **ff,
+ const apr_crypto_driver_t *provider, const char *params,
+ apr_pool_t *pool)
+{
+ apr_crypto_config_t *config = NULL;
+ apr_crypto_t *f = apr_pcalloc(pool, sizeof(apr_crypto_t));
+
+ const char *engine = NULL;
+
+ struct {
+ const char *field;
+ const char *value;
+ int set;
+ } fields[] = {
+ { "engine", NULL, 0 },
+ { NULL, NULL, 0 }
+ };
+ const char *ptr;
+ size_t klen;
+ char **elts = NULL;
+ char *elt;
+ int i = 0, j;
+ apr_status_t status;
+
+ if (params) {
+ if (APR_SUCCESS != (status = apr_tokenize_to_argv(params, &elts, pool))) {
+ return status;
+ }
+ while ((elt = elts[i])) {
+ ptr = strchr(elt, '=');
+ if (ptr) {
+ for (klen = ptr - elt; klen && apr_isspace(elt[klen - 1]); --klen)
+ ;
+ ptr++;
+ }
+ else {
+ for (klen = strlen(elt); klen && apr_isspace(elt[klen - 1]); --klen)
+ ;
+ }
+ elt[klen] = 0;
+
+ for (j = 0; fields[j].field != NULL; ++j) {
+ if (!strcasecmp(fields[j].field, elt)) {
+ fields[j].set = 1;
+ if (ptr) {
+ fields[j].value = ptr;
+ }
+ break;
+ }
+ }
+
+ i++;
+ }
+ engine = fields[0].value;
+ }
+
+ if (!f) {
+ return APR_ENOMEM;
+ }
+ *ff = f;
+ f->pool = pool;
+ f->provider = provider;
+ config = f->config = apr_pcalloc(pool, sizeof(apr_crypto_config_t));
+ if (!config) {
+ return APR_ENOMEM;
+ }
+
+ f->result = apr_pcalloc(pool, sizeof(apu_err_t));
+ if (!f->result) {
+ return APR_ENOMEM;
+ }
+
+ f->types = apr_hash_make(pool);
+ if (!f->types) {
+ return APR_ENOMEM;
+ }
+ apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0]));
+ apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1]));
+ apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_types[2]));
+ apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_types[3]));
+
+ f->modes = apr_hash_make(pool);
+ if (!f->modes) {
+ return APR_ENOMEM;
+ }
+ apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0]));
+ apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1]));
+
+ apr_pool_cleanup_register(pool, f, crypto_cleanup_helper,
+ apr_pool_cleanup_null);
+
+ if (engine) {
+ config->engine = ENGINE_by_id(engine);
+ if (!config->engine) {
+ return APR_ENOENGINE;
+ }
+ if (!ENGINE_init(config->engine)) {
+ ENGINE_free(config->engine);
+ config->engine = NULL;
+ return APR_EINITENGINE;
+ }
+ }
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Get a hash table of key types, keyed by the name of the type against
+ * a pointer to apr_crypto_block_key_type_t.
+ *
+ * @param types - hashtable of key types keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+static apr_status_t crypto_get_block_key_types(apr_hash_t **types,
+ const apr_crypto_t *f)
+{
+ *types = f->types;
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Get a hash table of key modes, keyed by the name of the mode against
+ * a pointer to apr_crypto_block_key_mode_t.
+ *
+ * @param modes - hashtable of key modes keyed to constants.
+ * @param f - encryption context
+ * @return APR_SUCCESS for success
+ */
+static apr_status_t crypto_get_block_key_modes(apr_hash_t **modes,
+ const apr_crypto_t *f)
+{
+ *modes = f->modes;
+ return APR_SUCCESS;
+}
+
+/*
+ * Work out which mechanism to use.
+ */
+static apr_status_t crypto_cipher_mechanism(apr_crypto_key_t *key,
+ const apr_crypto_block_key_type_e type,
+ const apr_crypto_block_key_mode_e mode, const int doPad, apr_pool_t *p)
+{
+ /* determine the cipher to be used */
+ switch (type) {
+
+ case (APR_KEY_3DES_192):
+
+ /* A 3DES key */
+ if (mode == APR_MODE_CBC) {
+ key->cipher = EVP_des_ede3_cbc();
+ }
+ else {
+ key->cipher = EVP_des_ede3_ecb();
+ }
+ break;
+
+ case (APR_KEY_AES_128):
+
+ if (mode == APR_MODE_CBC) {
+ key->cipher = EVP_aes_128_cbc();
+ }
+ else {
+ key->cipher = EVP_aes_128_ecb();
+ }
+ break;
+
+ case (APR_KEY_AES_192):
+
+ if (mode == APR_MODE_CBC) {
+ key->cipher = EVP_aes_192_cbc();
+ }
+ else {
+ key->cipher = EVP_aes_192_ecb();
+ }
+ break;
+
+ case (APR_KEY_AES_256):
+
+ if (mode == APR_MODE_CBC) {
+ key->cipher = EVP_aes_256_cbc();
+ }
+ else {
+ key->cipher = EVP_aes_256_ecb();
+ }
+ break;
+
+ default:
+
+ /* unknown key type, give up */
+ return APR_EKEYTYPE;
+
+ }
+
+ /* find the length of the key we need */
+ key->keyLen = EVP_CIPHER_key_length(key->cipher);
+
+ /* make space for the key */
+ key->key = apr_pcalloc(p, key->keyLen);
+ if (!key->key) {
+ return APR_ENOMEM;
+ }
+ apr_crypto_clear(p, key->key, key->keyLen);
+
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ * up when the context is cleaned, and may be reused with multiple encryption
+ * or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_key(apr_crypto_key_t **k,
+ const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
+{
+ apr_crypto_key_t *key = *k;
+ apr_status_t rv;
+
+ if (!key) {
+ *k = key = apr_pcalloc(p, sizeof *key);
+ if (!key) {
+ return APR_ENOMEM;
+ }
+ }
+
+ key->f = f;
+ key->provider = f->provider;
+
+ /* decide on what cipher mechanism we will be using */
+ rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad, p);
+ if (APR_SUCCESS != rv) {
+ return rv;
+ }
+
+ switch (rec->ktype) {
+
+ case APR_CRYPTO_KTYPE_PASSPHRASE: {
+
+ /* generate the key */
+ if (PKCS5_PBKDF2_HMAC_SHA1(rec->k.passphrase.pass,
+ rec->k.passphrase.passLen,
+ (unsigned char *) rec->k.passphrase.salt,
+ rec->k.passphrase.saltLen, rec->k.passphrase.iterations,
+ key->keyLen, key->key) == 0) {
+ return APR_ENOKEY;
+ }
+
+ break;
+ }
+
+ case APR_CRYPTO_KTYPE_SECRET: {
+
+ /* sanity check - key correct size? */
+ if (rec->k.secret.secretLen != key->keyLen) {
+ return APR_EKEYLENGTH;
+ }
+
+ /* copy the key */
+ memcpy(key->key, rec->k.secret.secret, rec->k.secret.secretLen);
+
+ break;
+ }
+
+ default: {
+
+ return APR_ENOKEY;
+
+ }
+ }
+
+ key->doPad = rec->pad;
+
+ /* note: openssl incorrectly returns non zero IV size values for ECB
+ * algorithms, so work around this by ignoring the IV size.
+ */
+ if (APR_MODE_ECB != rec->mode) {
+ key->ivSize = EVP_CIPHER_iv_length(key->cipher);
+ }
+
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the given passphrase. By default, the PBKDF2
+ * algorithm is used to generate the key from the passphrase. It is expected
+ * that the same pass phrase will generate the same key, regardless of the
+ * backend crypto platform used. The key is cleaned up when the context
+ * is cleaned, and may be reused with multiple encryption or decryption
+ * operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ * *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param ivSize The size of the initialisation vector will be returned, based
+ * on whether an IV is relevant for this type of crypto.
+ * @param pass The passphrase to use.
+ * @param passLen The passphrase length in bytes
+ * @param salt The salt to use.
+ * @param saltLen The salt length in bytes
+ * @param type 3DES_192, AES_128, AES_192, AES_256.
+ * @param mode Electronic Code Book / Cipher Block Chaining.
+ * @param doPad Pad if necessary.
+ * @param iterations Iteration count
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ * error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ * is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ * not known. APR_EPADDING if padding was requested but is not supported.
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
+ const char *pass, apr_size_t passLen, const unsigned char * salt,
+ apr_size_t saltLen, const apr_crypto_block_key_type_e type,
+ const apr_crypto_block_key_mode_e mode, const int doPad,
+ const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+{
+ apr_crypto_key_t *key = *k;
+ apr_status_t rv;
+
+ if (!key) {
+ *k = key = apr_pcalloc(p, sizeof *key);
+ if (!key) {
+ return APR_ENOMEM;
+ }
+ }
+
+ key->f = f;
+ key->provider = f->provider;
+
+ /* decide on what cipher mechanism we will be using */
+ rv = crypto_cipher_mechanism(key, type, mode, doPad, p);
+ if (APR_SUCCESS != rv) {
+ return rv;
+ }
+
+ /* generate the key */
+ if (PKCS5_PBKDF2_HMAC_SHA1(pass, passLen, (unsigned char *) salt, saltLen,
+ iterations, key->keyLen, key->key) == 0) {
+ return APR_ENOKEY;
+ }
+
+ key->doPad = doPad;
+
+ /* note: openssl incorrectly returns non zero IV size values for ECB
+ * algorithms, so work around this by ignoring the IV size.
+ */
+ if (APR_MODE_ECB != mode) {
+ key->ivSize = EVP_CIPHER_iv_length(key->cipher);
+ }
+ if (ivSize) {
+ *ivSize = key->ivSize;
+ }
+
+ return APR_SUCCESS;
+}
+
+/**
+ * @brief Initialise a context for encrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ * *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ * an IV will be created at random, in space allocated from the pool.
+ * If the buffer pointed to is not NULL, the IV in the buffer will be
+ * used.
+ * @param key The key structure.
+ * @param blockSize The block size of the cipher.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ * Returns APR_EINIT if the backend failed to initialise the context. Returns
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
+ const unsigned char **iv, const apr_crypto_key_t *key,
+ apr_size_t *blockSize, apr_pool_t *p)
+{
+ unsigned char *usedIv;
+ apr_crypto_config_t *config = key->f->config;
+ apr_crypto_block_t *block = *ctx;
+ if (!block) {
+ *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
+ }
+ if (!block) {
+ return APR_ENOMEM;
+ }
+ block->f = key->f;
+ block->pool = p;
+ block->provider = key->provider;
+
+ apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
+ apr_pool_cleanup_null);
+
+ /* create a new context for encryption */
+ if (!block->initialised) {
+ block->cipherCtx = EVP_CIPHER_CTX_new();
+ block->initialised = 1;
+ }
+
+ /* generate an IV, if necessary */
+ usedIv = NULL;
+ if (key->ivSize) {
+ if (iv == NULL) {
+ return APR_ENOIV;
+ }
+ if (*iv == NULL) {
+ usedIv = apr_pcalloc(p, key->ivSize);
+ if (!usedIv) {
+ return APR_ENOMEM;
+ }
+ apr_crypto_clear(p, usedIv, key->ivSize);
+ if (!((RAND_status() == 1)
+ && (RAND_bytes(usedIv, key->ivSize) == 1))) {
+ return APR_ENOIV;
+ }
+ *iv = usedIv;
+ }
+ else {
+ usedIv = (unsigned char *) *iv;
+ }
+ }
+
+ /* set up our encryption context */
+#if CRYPTO_OPENSSL_CONST_BUFFERS
+ if (!EVP_EncryptInit_ex(block->cipherCtx, key->cipher, config->engine,
+ key->key, usedIv)) {
+#else
+ if (!EVP_EncryptInit_ex(block->cipherCtx, key->cipher, config->engine, (unsigned char *) key->key, (unsigned char *) usedIv)) {
+#endif
+ return APR_EINIT;
+ }
+
+ /* Clear up any read padding */
+ if (!EVP_CIPHER_CTX_set_padding(block->cipherCtx, key->doPad)) {
+ return APR_EPADDING;
+ }
+
+ if (blockSize) {
+ *blockSize = EVP_CIPHER_block_size(key->cipher);
+ }
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Encrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ * out is NULL, outlen will contain the maximum size of the
+ * buffer needed to hold the data, including any data
+ * generated by apr_crypto_block_encrypt_finish below. If *out points
+ * to NULL, a buffer sufficiently large will be created from
+ * the pool provided. If *out points to a not-NULL value, this
+ * value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ * see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ * not implemented.
+ */
+static apr_status_t crypto_block_encrypt(unsigned char **out,
+ apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+ apr_crypto_block_t *ctx)
+{
+ int outl = *outlen;
+ unsigned char *buffer;
+
+ /* are we after the maximum size of the out buffer? */
+ if (!out) {
+ *outlen = inlen + EVP_MAX_BLOCK_LENGTH;
+ return APR_SUCCESS;
+ }
+
+ /* must we allocate the output buffer from a pool? */
+ if (!*out) {
+ buffer = apr_palloc(ctx->pool, inlen + EVP_MAX_BLOCK_LENGTH);
+ if (!buffer) {
+ return APR_ENOMEM;
+ }
+ apr_crypto_clear(ctx->pool, buffer, inlen + EVP_MAX_BLOCK_LENGTH);
+ *out = buffer;
+ }
+
+#if CRYPT_OPENSSL_CONST_BUFFERS
+ if (!EVP_EncryptUpdate(ctx->cipherCtx, (*out), &outl, in, inlen)) {
+#else
+ if (!EVP_EncryptUpdate(ctx->cipherCtx, (*out), &outl,
+ (unsigned char *) in, inlen)) {
+#endif
+#if APR_USE_OPENSSL_PRE_1_1_API
+ EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
+#else
+ EVP_CIPHER_CTX_reset(ctx->cipherCtx);
+#endif
+ return APR_ECRYPT;
+ }
+ *outlen = outl;
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Encrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ * padded. Typically the final block will be written to the
+ * same buffer used by apr_crypto_block_encrypt, offset by the
+ * number of bytes returned as actually written by the
+ * apr_crypto_block_encrypt() call. After this call, the context
+ * is cleaned and can be reused by apr_crypto_block_encrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ * buffer must already exist, and is usually the same
+ * buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ * formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_encrypt_finish(unsigned char *out,
+ apr_size_t *outlen, apr_crypto_block_t *ctx)
+{
+ apr_status_t rc = APR_SUCCESS;
+ int len = *outlen;
+
+ if (EVP_EncryptFinal_ex(ctx->cipherCtx, out, &len) == 0) {
+ rc = APR_EPADDING;
+ }
+ else {
+ *outlen = len;
+ }
+#if APR_USE_OPENSSL_PRE_1_1_API
+ EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
+#else
+ EVP_CIPHER_CTX_reset(ctx->cipherCtx);
+#endif
+
+ return rc;
+
+}
+
+/**
+ * @brief Initialise a context for decrypting arbitrary data using the given key.
+ * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
+ * *ctx is not NULL, *ctx must point at a previously created structure.
+ * @param ctx The block context returned, see note.
+ * @param blockSize The block size of the cipher.
+ * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
+ * an IV will be created at random, in space allocated from the pool.
+ * If the buffer is not NULL, the IV in the buffer will be used.
+ * @param key The key structure.
+ * @param p The pool to use.
+ * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
+ * Returns APR_EINIT if the backend failed to initialise the context. Returns
+ * APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
+ apr_size_t *blockSize, const unsigned char *iv,
+ const apr_crypto_key_t *key, apr_pool_t *p)
+{
+ apr_crypto_config_t *config = key->f->config;
+ apr_crypto_block_t *block = *ctx;
+ if (!block) {
+ *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
+ }
+ if (!block) {
+ return APR_ENOMEM;
+ }
+ block->f = key->f;
+ block->pool = p;
+ block->provider = key->provider;
+
+ apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
+ apr_pool_cleanup_null);
+
+ /* create a new context for encryption */
+ if (!block->initialised) {
+ block->cipherCtx = EVP_CIPHER_CTX_new();
+ block->initialised = 1;
+ }
+
+ /* generate an IV, if necessary */
+ if (key->ivSize) {
+ if (iv == NULL) {
+ return APR_ENOIV;
+ }
+ }
+
+ /* set up our encryption context */
+#if CRYPTO_OPENSSL_CONST_BUFFERS
+ if (!EVP_DecryptInit_ex(block->cipherCtx, key->cipher, config->engine,
+ key->key, iv)) {
+#else
+ if (!EVP_DecryptInit_ex(block->cipherCtx, key->cipher, config->engine, (unsigned char *) key->key, (unsigned char *) iv)) {
+#endif
+ return APR_EINIT;
+ }
+
+ /* Clear up any read padding */
+ if (!EVP_CIPHER_CTX_set_padding(block->cipherCtx, key->doPad)) {
+ return APR_EPADDING;
+ }
+
+ if (blockSize) {
+ *blockSize = EVP_CIPHER_block_size(key->cipher);
+ }
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Decrypt data provided by in, write it to out.
+ * @note The number of bytes written will be written to outlen. If
+ * out is NULL, outlen will contain the maximum size of the
+ * buffer needed to hold the data, including any data
+ * generated by apr_crypto_block_decrypt_finish below. If *out points
+ * to NULL, a buffer sufficiently large will be created from
+ * the pool provided. If *out points to a not-NULL value, this
+ * value will be used as a buffer instead.
+ * @param out Address of a buffer to which data will be written,
+ * see note.
+ * @param outlen Length of the output will be written here.
+ * @param in Address of the buffer to read.
+ * @param inlen Length of the buffer to read.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
+ * not implemented.
+ */
+static apr_status_t crypto_block_decrypt(unsigned char **out,
+ apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
+ apr_crypto_block_t *ctx)
+{
+ int outl = *outlen;
+ unsigned char *buffer;
+
+ /* are we after the maximum size of the out buffer? */
+ if (!out) {
+ *outlen = inlen + EVP_MAX_BLOCK_LENGTH;
+ return APR_SUCCESS;
+ }
+
+ /* must we allocate the output buffer from a pool? */
+ if (!(*out)) {
+ buffer = apr_palloc(ctx->pool, inlen + EVP_MAX_BLOCK_LENGTH);
+ if (!buffer) {
+ return APR_ENOMEM;
+ }
+ apr_crypto_clear(ctx->pool, buffer, inlen + EVP_MAX_BLOCK_LENGTH);
+ *out = buffer;
+ }
+
+#if CRYPT_OPENSSL_CONST_BUFFERS
+ if (!EVP_DecryptUpdate(ctx->cipherCtx, *out, &outl, in, inlen)) {
+#else
+ if (!EVP_DecryptUpdate(ctx->cipherCtx, *out, &outl, (unsigned char *) in,
+ inlen)) {
+#endif
+#if APR_USE_OPENSSL_PRE_1_1_API
+ EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
+#else
+ EVP_CIPHER_CTX_reset(ctx->cipherCtx);
+#endif
+ return APR_ECRYPT;
+ }
+ *outlen = outl;
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * @brief Decrypt final data block, write it to out.
+ * @note If necessary the final block will be written out after being
+ * padded. Typically the final block will be written to the
+ * same buffer used by apr_crypto_block_decrypt, offset by the
+ * number of bytes returned as actually written by the
+ * apr_crypto_block_decrypt() call. After this call, the context
+ * is cleaned and can be reused by apr_crypto_block_decrypt_init().
+ * @param out Address of a buffer to which data will be written. This
+ * buffer must already exist, and is usually the same
+ * buffer used by apr_evp_crypt(). See note.
+ * @param outlen Length of the output will be written here.
+ * @param ctx The block context to use.
+ * @return APR_ECRYPT if an error occurred.
+ * @return APR_EPADDING if padding was enabled and the block was incorrectly
+ * formatted.
+ * @return APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_block_decrypt_finish(unsigned char *out,
+ apr_size_t *outlen, apr_crypto_block_t *ctx)
+{
+ apr_status_t rc = APR_SUCCESS;
+ int len = *outlen;
+
+ if (EVP_DecryptFinal_ex(ctx->cipherCtx, out, &len) == 0) {
+ rc = APR_EPADDING;
+ }
+ else {
+ *outlen = len;
+ }
+#if APR_USE_OPENSSL_PRE_1_1_API
+ EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
+#else
+ EVP_CIPHER_CTX_reset(ctx->cipherCtx);
+#endif
+
+ return rc;
+
+}
+
+/**
+ * OpenSSL module.
+ */
+APU_MODULE_DECLARE_DATA const apr_crypto_driver_t apr_crypto_openssl_driver = {
+ "openssl", crypto_init, crypto_make, crypto_get_block_key_types,
+ crypto_get_block_key_modes, crypto_passphrase,
+ crypto_block_encrypt_init, crypto_block_encrypt,
+ crypto_block_encrypt_finish, crypto_block_decrypt_init,
+ crypto_block_decrypt, crypto_block_decrypt_finish,
+ crypto_block_cleanup, crypto_cleanup, crypto_shutdown, crypto_error,
+ crypto_key
+};
+
+#endif
diff --git a/crypto/apr_crypto_openssl.dep b/crypto/apr_crypto_openssl.dep
new file mode 100644
index 0000000..61bfb22
--- /dev/null
+++ b/crypto/apr_crypto_openssl.dep
@@ -0,0 +1,14 @@
+# Microsoft Developer Studio Generated Dependency File, included by apr_crypto_openssl.mak
+
+.\apr_crypto_openssl.c : \
+ "..\include\apr_buckets.h"\
+ "..\include\apr_crypto.h"\
+ "..\include\apu.h"\
+ "..\include\apu_errno.h"\
+ "..\include\private\apr_crypto_internal.h"\
+
+
+..\libaprutil.rc : \
+ "..\include\apu.h"\
+ "..\include\apu_version.h"\
+
diff --git a/crypto/apr_crypto_openssl.dsp b/crypto/apr_crypto_openssl.dsp
new file mode 100644
index 0000000..3319405
--- /dev/null
+++ b/crypto/apr_crypto_openssl.dsp
@@ -0,0 +1,203 @@
+# Microsoft Developer Studio Project File - Name="apr_crypto_openssl" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=apr_crypto_openssl - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "apr_crypto_openssl.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "apr_crypto_openssl.mak" CFG="apr_crypto_openssl - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "apr_crypto_openssl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_openssl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_openssl - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_openssl - x64 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "apr_crypto_openssl - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../../apr/include" /I "../include/private" /I "../../openssl/inc32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_OPENSSL=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_crypto_openssl_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/apr_crypto_openssl-1.res" /d DLL_NAME="apr_crypto_openssl" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libeay32.lib ssleay32.lib /libpath:..\..\openssl\out32dll /nologo /base:"0x6F100000" /subsystem:windows /MACHINE:X86 /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libeay32.lib ssleay32.lib /nologo /libpath:..\..\openssl\out32dll /base:"0x6F100000" /subsystem:windows /MACHINE:X86 /dll /incremental:no /debug /out:"Release\apr_crypto_openssl-1.dll" /pdb:"Release\apr_crypto_openssl-1.pdb" /implib:"Release\apr_crypto_openssl-1.lib" /opt:ref
+# Begin Special Build Tool
+TargetPath=Release\apr_crypto_openssl-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "apr_crypto_openssl - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../../apr/include" /I "../include/private" /I "../../openssl/inc32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_OPENSSL=1 /D /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_crypto_openssl_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/apr_crypto_openssl-1.res" /d DLL_NAME="apr_crypto_openssl" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libeay32.lib ssleay32.lib /nologo /libpath:..\..\openssl\out32dll /base:"0x6F100000" /subsystem:windows /MACHINE:X86 /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libeay32.lib ssleay32.lib /nologo /libpath:..\..\openssl\out32dll /base:"0x6F100000" /subsystem:windows /MACHINE:X86 /dll /incremental:no /debug /out:"Debug\apr_crypto_openssl-1.dll" /pdb:"Debug\apr_crypto_openssl-1.pdb" /implib:"Debug\apr_crypto_openssl-1.lib"
+# Begin Special Build Tool
+TargetPath=Debug\apr_crypto_openssl-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "apr_crypto_openssl - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "WIN64" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../../apr/include" /I "../include/private" /I "../../openssl/inc32" /D "NDEBUG" /D "WIN32" /D "WIN64" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_OPENSSL=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_crypto_openssl_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /x64 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /x64 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"x64\Release/apr_crypto_openssl-1.res" /d DLL_NAME="apr_crypto_openssl" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libeay32.lib ssleay32.lib /nologo /libpath:..\..\openssl\out32dll /base:"0x6F100000" /subsystem:windows /machine:X64 /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libeay32.lib ssleay32.lib /nologo /libpath:..\..\openssl\out32dll /base:"0x6F100000" /subsystem:windows /machine:X64 /dll /incremental:no /debug /out:"x64\Release\apr_crypto_openssl-1.dll" /pdb:"x64\Release\apr_crypto_openssl-1.pdb" /implib:"x64\Release\apr_crypto_openssl-1.lib" /opt:ref
+# Begin Special Build Tool
+TargetPath=x64\Release\apr_crypto_openssl-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "apr_crypto_openssl - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\Debug"
+# PROP Intermediate_Dir "x64\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "WIN64" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../../apr/include" /I "../include/private" /I "../../openssl/inc32" /D "_DEBUG" /D "WIN32" /D "WIN64" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_OPENSSL=1 /D /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_crypto_openssl_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /x64 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /x64 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"x64\Debug/apr_crypto_openssl-1.res" /d DLL_NAME="apr_crypto_openssl" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libeay32.lib ssleay32.lib /nologo /libpath:..\..\openssl\out32dll /base:"0x6F100000" /subsystem:windows /machine:X64 /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libeay32.lib ssleay32.lib /nologo /libpath:..\..\openssl\out32dll /base:"0x6F100000" /subsystem:windows /machine:X64 /dll /incremental:no /debug /out:"x64\Debug\apr_crypto_openssl-1.dll" /pdb:"x64\Debug\apr_crypto_openssl-1.pdb" /implib:"x64\Debug\apr_crypto_openssl-1.lib"
+# Begin Special Build Tool
+TargetPath=x64\Debug\apr_crypto_openssl-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "apr_crypto_openssl - Win32 Release"
+# Name "apr_crypto_openssl - Win32 Debug"
+# Name "apr_crypto_openssl - x64 Release"
+# Name "apr_crypto_openssl - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\apr_crypto_openssl.c
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\apr_crypto.h
+# End Source File
+# End Group
+# Begin Group "Internal Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\private\apu_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_internal.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\libaprutil.rc
+# End Source File
+# End Target
+# End Project
diff --git a/crypto/apr_crypto_openssl.mak b/crypto/apr_crypto_openssl.mak
new file mode 100644
index 0000000..83968d5
--- /dev/null
+++ b/crypto/apr_crypto_openssl.mak
@@ -0,0 +1,606 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on apr_crypto_openssl.dsp
+!IF "$(CFG)" == ""
+CFG=apr_crypto_openssl - Win32 Release
+!MESSAGE No configuration specified. Defaulting to apr_crypto_openssl - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "apr_crypto_openssl - Win32 Release" && "$(CFG)" != "apr_crypto_openssl - Win32 Debug" && "$(CFG)" != "apr_crypto_openssl - x64 Release" && "$(CFG)" != "apr_crypto_openssl - x64 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "apr_crypto_openssl.mak" CFG="apr_crypto_openssl - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "apr_crypto_openssl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_openssl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_openssl - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_crypto_openssl - x64 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(_HAVE_OSSL110)" == "1"
+SSLCRP=libcrypto
+SSLLIB=libssl
+SSLINC=/I ../../openssl/include
+SSLBIN=/libpath:../../openssl
+!ELSE
+SSLCRP=libeay32
+SSLLIB=ssleay32
+SSLINC=/I ../../openssl/inc32
+SSLBIN=/libpath:../../openssl/out32dll
+!ENDIF
+
+!IF "$(CFG)" == "apr_crypto_openssl - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\apr_crypto_openssl-1.dll" "$(DS_POSTBUILD_DEP)"
+
+!ELSE
+
+ALL : "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\apr_crypto_openssl-1.dll" "$(DS_POSTBUILD_DEP)"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\apr_crypto_openssl-1.res"
+ -@erase "$(INTDIR)\apr_crypto_openssl.obj"
+ -@erase "$(INTDIR)\apr_crypto_openssl_src.idb"
+ -@erase "$(INTDIR)\apr_crypto_openssl_src.pdb"
+ -@erase "$(OUTDIR)\apr_crypto_openssl-1.dll"
+ -@erase "$(OUTDIR)\apr_crypto_openssl-1.exp"
+ -@erase "$(OUTDIR)\apr_crypto_openssl-1.lib"
+ -@erase "$(OUTDIR)\apr_crypto_openssl-1.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../../apr/include" /I "../include/private" $(SSLINC) /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_OPENSSL=1 /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\apr_crypto_openssl_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\apr_crypto_openssl-1.res" /i "../include" /i "../../apr/include" /d DLL_NAME="apr_crypto_openssl" /d "NDEBUG" /d "APU_VERSION_ONLY"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\apr_crypto_openssl.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib $(SSLCRP).lib $(SSLLIB).lib /nologo /base:"0x6F100000" /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\apr_crypto_openssl-1.pdb" /debug /out:"$(OUTDIR)\apr_crypto_openssl-1.dll" /implib:"$(OUTDIR)\apr_crypto_openssl-1.lib" $(SSLBIN) /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\apr_crypto_openssl.obj" \
+ "$(INTDIR)\apr_crypto_openssl-1.res" \
+ "..\..\apr\Release\libapr-1.lib" \
+ "..\Release\libaprutil-1.lib"
+
+"$(OUTDIR)\apr_crypto_openssl-1.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+TargetPath=.\Release\apr_crypto_openssl-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\apr_crypto_openssl-1.dll"
+ if exist .\Release\apr_crypto_openssl-1.dll.manifest mt.exe -manifest .\Release\apr_crypto_openssl-1.dll.manifest -outputresource:.\Release\apr_crypto_openssl-1.dll;2
+ echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
+
+!ELSEIF "$(CFG)" == "apr_crypto_openssl - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\apr_crypto_openssl-1.dll" "$(DS_POSTBUILD_DEP)"
+
+!ELSE
+
+ALL : "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\apr_crypto_openssl-1.dll" "$(DS_POSTBUILD_DEP)"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\apr_crypto_openssl-1.res"
+ -@erase "$(INTDIR)\apr_crypto_openssl.obj"
+ -@erase "$(INTDIR)\apr_crypto_openssl_src.idb"
+ -@erase "$(INTDIR)\apr_crypto_openssl_src.pdb"
+ -@erase "$(OUTDIR)\apr_crypto_openssl-1.dll"
+ -@erase "$(OUTDIR)\apr_crypto_openssl-1.exp"
+ -@erase "$(OUTDIR)\apr_crypto_openssl-1.lib"
+ -@erase "$(OUTDIR)\apr_crypto_openssl-1.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../include" /I "../../apr/include" /I "../include/private" $(SSLINC) /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_OPENSSL=1 /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\apr_crypto_openssl_src" /FD /D /EHsc /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\apr_crypto_openssl-1.res" /i "../include" /i "../../apr/include" /d DLL_NAME="apr_crypto_openssl" /d "_DEBUG" /d "APU_VERSION_ONLY"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\apr_crypto_openssl.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib $(SSLCRP).lib $(SSLLIB).lib /nologo /base:"0x6F100000" /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\apr_crypto_openssl-1.pdb" /debug /out:"$(OUTDIR)\apr_crypto_openssl-1.dll" /implib:"$(OUTDIR)\apr_crypto_openssl-1.lib" $(SSLBIN)
+LINK32_OBJS= \
+ "$(INTDIR)\apr_crypto_openssl.obj" \
+ "$(INTDIR)\apr_crypto_openssl-1.res" \
+ "..\..\apr\Debug\libapr-1.lib" \
+ "..\Debug\libaprutil-1.lib"
+
+"$(OUTDIR)\apr_crypto_openssl-1.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+TargetPath=.\Debug\apr_crypto_openssl-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\apr_crypto_openssl-1.dll"
+ if exist .\Debug\apr_crypto_openssl-1.dll.manifest mt.exe -manifest .\Debug\apr_crypto_openssl-1.dll.manifest -outputresource:.\Debug\apr_crypto_openssl-1.dll;2
+ echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
+
+!ELSEIF "$(CFG)" == "apr_crypto_openssl - x64 Release"
+
+OUTDIR=.\x64\Release
+INTDIR=.\x64\Release
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+# Begin Custom Macros
+OutDir=.\x64\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\apr_crypto_openssl-1.dll" "$(DS_POSTBUILD_DEP)"
+
+!ELSE
+
+ALL : "libaprutil - x64 Release" "libapr - x64 Release" "$(OUTDIR)\apr_crypto_openssl-1.dll" "$(DS_POSTBUILD_DEP)"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libapr - x64 ReleaseCLEAN" "libaprutil - x64 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\apr_crypto_openssl-1.res"
+ -@erase "$(INTDIR)\apr_crypto_openssl.obj"
+ -@erase "$(INTDIR)\apr_crypto_openssl_src.idb"
+ -@erase "$(INTDIR)\apr_crypto_openssl_src.pdb"
+ -@erase "$(OUTDIR)\apr_crypto_openssl-1.dll"
+ -@erase "$(OUTDIR)\apr_crypto_openssl-1.exp"
+ -@erase "$(OUTDIR)\apr_crypto_openssl-1.lib"
+ -@erase "$(OUTDIR)\apr_crypto_openssl-1.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../../apr/include" /I "../include/private" $(SSLINC) /D "NDEBUG" /D "WIN32" /D "WIN64" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_OPENSSL=1 /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\apr_crypto_openssl_src" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /x64 "NUL"
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\apr_crypto_openssl-1.res" /i "../include" /i "../../apr/include" /d DLL_NAME="apr_crypto_openssl" /d "NDEBUG" /d "APU_VERSION_ONLY"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\apr_crypto_openssl.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib $(SSLCRP).lib $(SSLLIB).lib /nologo /base:"0x6F100000" /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\apr_crypto_openssl-1.pdb" /debug /out:"$(OUTDIR)\apr_crypto_openssl-1.dll" /implib:"$(OUTDIR)\apr_crypto_openssl-1.lib" $(SSLBIN) /opt:ref
+LINK32_OBJS= \
+ "$(INTDIR)\apr_crypto_openssl.obj" \
+ "$(INTDIR)\apr_crypto_openssl-1.res" \
+ "..\..\apr\x64\Release\libapr-1.lib" \
+ "..\x64\Release\libaprutil-1.lib"
+
+"$(OUTDIR)\apr_crypto_openssl-1.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+TargetPath=.\x64\Release\apr_crypto_openssl-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+
+# Begin Custom Macros
+OutDir=.\x64\Release
+# End Custom Macros
+
+"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\apr_crypto_openssl-1.dll"
+ if exist .\x64\Release\apr_crypto_openssl-1.dll.manifest mt.exe -manifest .\x64\Release\apr_crypto_openssl-1.dll.manifest -outputresource:.\x64\Release\apr_crypto_openssl-1.dll;2
+ echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
+
+!ELSEIF "$(CFG)" == "apr_crypto_openssl - x64 Debug"
+
+OUTDIR=.\x64\Debug
+INTDIR=.\x64\Debug
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+# Begin Custom Macros
+OutDir=.\x64\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\apr_crypto_openssl-1.dll" "$(DS_POSTBUILD_DEP)"
+
+!ELSE
+
+ALL : "libaprutil - x64 Debug" "libapr - x64 Debug" "$(OUTDIR)\apr_crypto_openssl-1.dll" "$(DS_POSTBUILD_DEP)"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libapr - x64 DebugCLEAN" "libaprutil - x64 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\apr_crypto_openssl-1.res"
+ -@erase "$(INTDIR)\apr_crypto_openssl.obj"
+ -@erase "$(INTDIR)\apr_crypto_openssl_src.idb"
+ -@erase "$(INTDIR)\apr_crypto_openssl_src.pdb"
+ -@erase "$(OUTDIR)\apr_crypto_openssl-1.dll"
+ -@erase "$(OUTDIR)\apr_crypto_openssl-1.exp"
+ -@erase "$(OUTDIR)\apr_crypto_openssl-1.lib"
+ -@erase "$(OUTDIR)\apr_crypto_openssl-1.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../include" /I "../../apr/include" /I "../include/private" $(SSLINC) /D "_DEBUG" /D "WIN32" /D "WIN64" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_OPENSSL=1 /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\apr_crypto_openssl_src" /FD /D /EHsc /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /x64 "NUL"
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\apr_crypto_openssl-1.res" /i "../include" /i "../../apr/include" /d DLL_NAME="apr_crypto_openssl" /d "_DEBUG" /d "APU_VERSION_ONLY"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\apr_crypto_openssl.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib $(SSLCRP).lib $(SSLLIB).lib /nologo /base:"0x6F100000" /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\apr_crypto_openssl-1.pdb" /debug /out:"$(OUTDIR)\apr_crypto_openssl-1.dll" /implib:"$(OUTDIR)\apr_crypto_openssl-1.lib" $(SSLBIN)
+LINK32_OBJS= \
+ "$(INTDIR)\apr_crypto_openssl.obj" \
+ "$(INTDIR)\apr_crypto_openssl-1.res" \
+ "..\..\apr\x64\Debug\libapr-1.lib" \
+ "..\x64\Debug\libaprutil-1.lib"
+
+"$(OUTDIR)\apr_crypto_openssl-1.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+TargetPath=.\x64\Debug\apr_crypto_openssl-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
+
+# Begin Custom Macros
+OutDir=.\x64\Debug
+# End Custom Macros
+
+"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\apr_crypto_openssl-1.dll"
+ if exist .\x64\Debug\apr_crypto_openssl-1.dll.manifest mt.exe -manifest .\x64\Debug\apr_crypto_openssl-1.dll.manifest -outputresource:.\x64\Debug\apr_crypto_openssl-1.dll;2
+ echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("apr_crypto_openssl.dep")
+!INCLUDE "apr_crypto_openssl.dep"
+!ELSE
+!MESSAGE Warning: cannot find "apr_crypto_openssl.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "apr_crypto_openssl - Win32 Release" || "$(CFG)" == "apr_crypto_openssl - Win32 Debug" || "$(CFG)" == "apr_crypto_openssl - x64 Release" || "$(CFG)" == "apr_crypto_openssl - x64 Debug"
+SOURCE=.\apr_crypto_openssl.c
+
+"$(INTDIR)\apr_crypto_openssl.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!IF "$(CFG)" == "apr_crypto_openssl - Win32 Release"
+
+"libapr - Win32 Release" :
+ cd ".\..\..\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release"
+ cd "..\apr-util\crypto"
+
+"libapr - Win32 ReleaseCLEAN" :
+ cd ".\..\..\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN
+ cd "..\apr-util\crypto"
+
+!ELSEIF "$(CFG)" == "apr_crypto_openssl - Win32 Debug"
+
+"libapr - Win32 Debug" :
+ cd ".\..\..\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug"
+ cd "..\apr-util\crypto"
+
+"libapr - Win32 DebugCLEAN" :
+ cd ".\..\..\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\apr-util\crypto"
+
+!ELSEIF "$(CFG)" == "apr_crypto_openssl - x64 Release"
+
+"libapr - x64 Release" :
+ cd ".\..\..\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - x64 Release"
+ cd "..\apr-util\crypto"
+
+"libapr - x64 ReleaseCLEAN" :
+ cd ".\..\..\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - x64 Release" RECURSE=1 CLEAN
+ cd "..\apr-util\crypto"
+
+!ELSEIF "$(CFG)" == "apr_crypto_openssl - x64 Debug"
+
+"libapr - x64 Debug" :
+ cd ".\..\..\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - x64 Debug"
+ cd "..\apr-util\crypto"
+
+"libapr - x64 DebugCLEAN" :
+ cd ".\..\..\apr"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - x64 Debug" RECURSE=1 CLEAN
+ cd "..\apr-util\crypto"
+
+!ENDIF
+
+!IF "$(CFG)" == "apr_crypto_openssl - Win32 Release"
+
+"libaprutil - Win32 Release" :
+ cd ".\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release"
+ cd ".\crypto"
+
+"libaprutil - Win32 ReleaseCLEAN" :
+ cd ".\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN
+ cd ".\crypto"
+
+!ELSEIF "$(CFG)" == "apr_crypto_openssl - Win32 Debug"
+
+"libaprutil - Win32 Debug" :
+ cd ".\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug"
+ cd ".\crypto"
+
+"libaprutil - Win32 DebugCLEAN" :
+ cd ".\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN
+ cd ".\crypto"
+
+!ELSEIF "$(CFG)" == "apr_crypto_openssl - x64 Release"
+
+"libaprutil - x64 Release" :
+ cd ".\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - x64 Release"
+ cd ".\crypto"
+
+"libaprutil - x64 ReleaseCLEAN" :
+ cd ".\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - x64 Release" RECURSE=1 CLEAN
+ cd ".\crypto"
+
+!ELSEIF "$(CFG)" == "apr_crypto_openssl - x64 Debug"
+
+"libaprutil - x64 Debug" :
+ cd ".\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - x64 Debug"
+ cd ".\crypto"
+
+"libaprutil - x64 DebugCLEAN" :
+ cd ".\.."
+ $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - x64 Debug" RECURSE=1 CLEAN
+ cd ".\crypto"
+
+!ENDIF
+
+SOURCE=..\libaprutil.rc
+
+!IF "$(CFG)" == "apr_crypto_openssl - Win32 Release"
+
+
+"$(INTDIR)\apr_crypto_openssl-1.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)\apr_crypto_openssl-1.res" /i "../include" /i "../../apr/include" /i "\httpd-2.4.4\srclib\apr-util" /d DLL_NAME="apr_crypto_openssl" /d "NDEBUG" /d "APU_VERSION_ONLY" $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "apr_crypto_openssl - Win32 Debug"
+
+
+"$(INTDIR)\apr_crypto_openssl-1.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)\apr_crypto_openssl-1.res" /i "../include" /i "../../apr/include" /i "\httpd-2.4.4\srclib\apr-util" /d DLL_NAME="apr_crypto_openssl" /d "_DEBUG" /d "APU_VERSION_ONLY" $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "apr_crypto_openssl - x64 Release"
+
+
+"$(INTDIR)\apr_crypto_openssl-1.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)\apr_crypto_openssl-1.res" /i "../include" /i "../../apr/include" /i "\httpd-2.4.4\srclib\apr-util" /d DLL_NAME="apr_crypto_openssl" /d "NDEBUG" /d "APU_VERSION_ONLY" $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "apr_crypto_openssl - x64 Debug"
+
+
+"$(INTDIR)\apr_crypto_openssl-1.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)\apr_crypto_openssl-1.res" /i "../include" /i "../../apr/include" /i "\httpd-2.4.4\srclib\apr-util" /d DLL_NAME="apr_crypto_openssl" /d "_DEBUG" /d "APU_VERSION_ONLY" $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
diff --git a/crypto/apr_md4.c b/crypto/apr_md4.c
new file mode 100644
index 0000000..9d58193
--- /dev/null
+++ b/crypto/apr_md4.c
@@ -0,0 +1,409 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This is derived from material copyright RSA Data Security, Inc.
+ * Their notice is reproduced below in its entirety.
+ *
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD4 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ */
+
+#include "apr_strings.h"
+#include "apr_md4.h"
+#include "apr_lib.h"
+#include "apr_crypto.h" /* for apr_crypto_memzero, if available */
+
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* Constants for MD4Transform routine.
+ */
+
+#define S11 3
+#define S12 7
+#define S13 11
+#define S14 19
+#define S21 3
+#define S22 5
+#define S23 9
+#define S24 13
+#define S31 3
+#define S32 9
+#define S33 11
+#define S34 15
+
+static void MD4Transform(apr_uint32_t state[4], const unsigned char block[64]);
+static void Encode(unsigned char *output, const apr_uint32_t *input,
+ unsigned int len);
+static void Decode(apr_uint32_t *output, const unsigned char *input,
+ unsigned int len);
+
+static unsigned char PADDING[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#if APR_CHARSET_EBCDIC
+static apr_xlate_t *xlate_ebcdic_to_ascii; /* used in apr_md4_encode() */
+#endif
+
+/* F, G and I are basic MD4 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
+/* Rotation is separate from addition to prevent recomputation */
+
+#define FF(a, b, c, d, x, s) { \
+ (a) += F ((b), (c), (d)) + (x); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+#define GG(a, b, c, d, x, s) { \
+ (a) += G ((b), (c), (d)) + (x) + (apr_uint32_t)0x5a827999; \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+#define HH(a, b, c, d, x, s) { \
+ (a) += H ((b), (c), (d)) + (x) + (apr_uint32_t)0x6ed9eba1; \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+
+/* MD4 initialization. Begins an MD4 operation, writing a new context.
+ */
+APU_DECLARE(apr_status_t) apr_md4_init(apr_md4_ctx_t *context)
+{
+ context->count[0] = context->count[1] = 0;
+
+ /* Load magic initialization constants. */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+
+#if APR_HAS_XLATE
+ context->xlate = NULL;
+#endif
+
+ return APR_SUCCESS;
+}
+
+#if APR_HAS_XLATE
+/* MD4 translation setup. Provides the APR translation handle
+ * to be used for translating the content before calculating the
+ * digest.
+ */
+APU_DECLARE(apr_status_t) apr_md4_set_xlate(apr_md4_ctx_t *context,
+ apr_xlate_t *xlate)
+{
+ apr_status_t rv;
+ int is_sb;
+
+ /* TODO: remove the single-byte-only restriction from this code
+ */
+ rv = apr_xlate_sb_get(xlate, &is_sb);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ if (!is_sb) {
+ return APR_EINVAL;
+ }
+ context->xlate = xlate;
+ return APR_SUCCESS;
+}
+#endif /* APR_HAS_XLATE */
+
+/* MD4 block update operation. Continues an MD4 message-digest
+ * operation, processing another message block, and updating the
+ * context.
+ */
+APU_DECLARE(apr_status_t) apr_md4_update(apr_md4_ctx_t *context,
+ const unsigned char *input,
+ apr_size_t inputLen)
+{
+ unsigned int i, idx, partLen;
+#if APR_HAS_XLATE
+ apr_size_t inbytes_left, outbytes_left;
+#endif
+
+ /* Compute number of bytes mod 64 */
+ idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ((context->count[0] += ((apr_uint32_t)inputLen << 3))
+ < ((apr_uint32_t)inputLen << 3))
+ context->count[1]++;
+ context->count[1] += (apr_uint32_t)inputLen >> 29;
+
+ partLen = 64 - idx;
+
+ /* Transform as many times as possible. */
+#if !APR_HAS_XLATE
+ if (inputLen >= partLen) {
+ memcpy(&context->buffer[idx], input, partLen);
+ MD4Transform(context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ MD4Transform(context->state, &input[i]);
+
+ idx = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ memcpy(&context->buffer[idx], &input[i], inputLen - i);
+#else /*APR_HAS_XLATE*/
+ if (inputLen >= partLen) {
+ if (context->xlate) {
+ inbytes_left = outbytes_left = partLen;
+ apr_xlate_conv_buffer(context->xlate, (const char *)input,
+ &inbytes_left,
+ (char *)&context->buffer[idx],
+ &outbytes_left);
+ }
+ else {
+ memcpy(&context->buffer[idx], input, partLen);
+ }
+ MD4Transform(context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64) {
+ if (context->xlate) {
+ unsigned char inp_tmp[64];
+ inbytes_left = outbytes_left = 64;
+ apr_xlate_conv_buffer(context->xlate, (const char *)&input[i],
+ &inbytes_left,
+ (char *)inp_tmp, &outbytes_left);
+ MD4Transform(context->state, inp_tmp);
+ }
+ else {
+ MD4Transform(context->state, &input[i]);
+ }
+ }
+
+ idx = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ if (context->xlate) {
+ inbytes_left = outbytes_left = inputLen - i;
+ apr_xlate_conv_buffer(context->xlate, (const char *)&input[i],
+ &inbytes_left, (char *)&context->buffer[idx],
+ &outbytes_left);
+ }
+ else {
+ memcpy(&context->buffer[idx], &input[i], inputLen - i);
+ }
+#endif /*APR_HAS_XLATE*/
+ return APR_SUCCESS;
+}
+
+/* MD4 finalization. Ends an MD4 message-digest operation, writing the
+ * the message digest and zeroizing the context.
+ */
+APU_DECLARE(apr_status_t) apr_md4_final(
+ unsigned char digest[APR_MD4_DIGESTSIZE],
+ apr_md4_ctx_t *context)
+{
+ unsigned char bits[8];
+ unsigned int idx, padLen;
+
+ /* Save number of bits */
+ Encode(bits, context->count, 8);
+
+#if APR_HAS_XLATE
+ /* apr_md4_update() should not translate for this final round. */
+ context->xlate = NULL;
+#endif /*APR_HAS_XLATE*/
+
+ /* Pad out to 56 mod 64. */
+ idx = (unsigned int) ((context->count[0] >> 3) & 0x3f);
+ padLen = (idx < 56) ? (56 - idx) : (120 - idx);
+ apr_md4_update(context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ apr_md4_update(context, bits, 8);
+
+ /* Store state in digest */
+ Encode(digest, context->state, APR_MD4_DIGESTSIZE);
+
+ /* Zeroize sensitive information. */
+ memset(context, 0, sizeof(*context));
+
+ return APR_SUCCESS;
+}
+
+/* MD4 computation in one step (init, update, final)
+ */
+APU_DECLARE(apr_status_t) apr_md4(unsigned char digest[APR_MD4_DIGESTSIZE],
+ const unsigned char *input,
+ apr_size_t inputLen)
+{
+ apr_md4_ctx_t ctx;
+ apr_status_t rv;
+
+ apr_md4_init(&ctx);
+
+ if ((rv = apr_md4_update(&ctx, input, inputLen)) != APR_SUCCESS)
+ return rv;
+
+ return apr_md4_final(digest, &ctx);
+}
+
+/* MD4 basic transformation. Transforms state based on block. */
+static void MD4Transform(apr_uint32_t state[4], const unsigned char block[64])
+{
+ apr_uint32_t a = state[0], b = state[1], c = state[2], d = state[3],
+ x[APR_MD4_DIGESTSIZE];
+
+ Decode(x, block, 64);
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], S11); /* 1 */
+ FF (d, a, b, c, x[ 1], S12); /* 2 */
+ FF (c, d, a, b, x[ 2], S13); /* 3 */
+ FF (b, c, d, a, x[ 3], S14); /* 4 */
+ FF (a, b, c, d, x[ 4], S11); /* 5 */
+ FF (d, a, b, c, x[ 5], S12); /* 6 */
+ FF (c, d, a, b, x[ 6], S13); /* 7 */
+ FF (b, c, d, a, x[ 7], S14); /* 8 */
+ FF (a, b, c, d, x[ 8], S11); /* 9 */
+ FF (d, a, b, c, x[ 9], S12); /* 10 */
+ FF (c, d, a, b, x[10], S13); /* 11 */
+ FF (b, c, d, a, x[11], S14); /* 12 */
+ FF (a, b, c, d, x[12], S11); /* 13 */
+ FF (d, a, b, c, x[13], S12); /* 14 */
+ FF (c, d, a, b, x[14], S13); /* 15 */
+ FF (b, c, d, a, x[15], S14); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 0], S21); /* 17 */
+ GG (d, a, b, c, x[ 4], S22); /* 18 */
+ GG (c, d, a, b, x[ 8], S23); /* 19 */
+ GG (b, c, d, a, x[12], S24); /* 20 */
+ GG (a, b, c, d, x[ 1], S21); /* 21 */
+ GG (d, a, b, c, x[ 5], S22); /* 22 */
+ GG (c, d, a, b, x[ 9], S23); /* 23 */
+ GG (b, c, d, a, x[13], S24); /* 24 */
+ GG (a, b, c, d, x[ 2], S21); /* 25 */
+ GG (d, a, b, c, x[ 6], S22); /* 26 */
+ GG (c, d, a, b, x[10], S23); /* 27 */
+ GG (b, c, d, a, x[14], S24); /* 28 */
+ GG (a, b, c, d, x[ 3], S21); /* 29 */
+ GG (d, a, b, c, x[ 7], S22); /* 30 */
+ GG (c, d, a, b, x[11], S23); /* 31 */
+ GG (b, c, d, a, x[15], S24); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 0], S31); /* 33 */
+ HH (d, a, b, c, x[ 8], S32); /* 34 */
+ HH (c, d, a, b, x[ 4], S33); /* 35 */
+ HH (b, c, d, a, x[12], S34); /* 36 */
+ HH (a, b, c, d, x[ 2], S31); /* 37 */
+ HH (d, a, b, c, x[10], S32); /* 38 */
+ HH (c, d, a, b, x[ 6], S33); /* 39 */
+ HH (b, c, d, a, x[14], S34); /* 40 */
+ HH (a, b, c, d, x[ 1], S31); /* 41 */
+ HH (d, a, b, c, x[ 9], S32); /* 42 */
+ HH (c, d, a, b, x[ 5], S33); /* 43 */
+ HH (b, c, d, a, x[13], S34); /* 44 */
+ HH (a, b, c, d, x[ 3], S31); /* 45 */
+ HH (d, a, b, c, x[11], S32); /* 46 */
+ HH (c, d, a, b, x[ 7], S33); /* 47 */
+ HH (b, c, d, a, x[15], S34); /* 48 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information. */
+#if APU_HAVE_CRYPTO
+ apr_crypto_memzero(x, sizeof(x));
+#else
+ memset(x, 0, sizeof(x));
+#endif
+}
+
+/* Encodes input (apr_uint32_t) into output (unsigned char). Assumes len is
+ * a multiple of 4.
+ */
+static void Encode(unsigned char *output, const apr_uint32_t *input,
+ unsigned int len)
+{
+ unsigned int i, j;
+ apr_uint32_t k;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ k = input[i];
+ output[j] = (unsigned char)(k & 0xff);
+ output[j + 1] = (unsigned char)((k >> 8) & 0xff);
+ output[j + 2] = (unsigned char)((k >> 16) & 0xff);
+ output[j + 3] = (unsigned char)((k >> 24) & 0xff);
+ }
+}
+
+/* Decodes input (unsigned char) into output (apr_uint32_t). Assumes len is
+ * a multiple of 4.
+ */
+static void Decode(apr_uint32_t *output, const unsigned char *input,
+ unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((apr_uint32_t)input[j]) |
+ (((apr_uint32_t)input[j + 1]) << 8) |
+ (((apr_uint32_t)input[j + 2]) << 16) |
+ (((apr_uint32_t)input[j + 3]) << 24);
+}
+
+#if APR_CHARSET_EBCDIC
+APU_DECLARE(apr_status_t) apr_MD4InitEBCDIC(apr_xlate_t *xlate)
+{
+ xlate_ebcdic_to_ascii = xlate;
+ return APR_SUCCESS;
+}
+#endif
diff --git a/crypto/apr_md5.c b/crypto/apr_md5.c
new file mode 100644
index 0000000..40fa7b2
--- /dev/null
+++ b/crypto/apr_md5.c
@@ -0,0 +1,666 @@
+/*
+ * This is work is derived from material Copyright RSA Data Security, Inc.
+ *
+ * The RSA copyright statement and Licence for that original material is
+ * included below. This is followed by the Apache copyright statement and
+ * licence for the modifications made to that material.
+ */
+
+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ rights reserved.
+
+ License to copy and use this software is granted provided that it
+ is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ License is also granted to make and use derivative works provided
+ that such works are identified as "derived from the RSA Data
+ Security, Inc. MD5 Message-Digest Algorithm" in all material
+ mentioning or referencing the derived work.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * The apr_md5_encode() routine uses much code obtained from the FreeBSD 3.0
+ * MD5 crypt() function, which is licenced as follows:
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ */
+#include "apr_strings.h"
+#include "apr_md5.h"
+#include "apr_lib.h"
+#include "apu_config.h"
+
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+
+/* Constants for MD5Transform routine.
+ */
+
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static void MD5Transform(apr_uint32_t state[4], const unsigned char block[64]);
+static void Encode(unsigned char *output, const apr_uint32_t *input,
+ unsigned int len);
+static void Decode(apr_uint32_t *output, const unsigned char *input,
+ unsigned int len);
+
+static const unsigned char PADDING[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#if APR_CHARSET_EBCDIC
+static apr_xlate_t *xlate_ebcdic_to_ascii; /* used in apr_md5_encode() */
+#endif
+#define DO_XLATE 0
+#define SKIP_XLATE 1
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+ * Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+APU_DECLARE(apr_status_t) apr_md5_init(apr_md5_ctx_t *context)
+{
+ context->count[0] = context->count[1] = 0;
+
+ /* Load magic initialization constants. */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+ context->xlate = NULL;
+
+ return APR_SUCCESS;
+}
+
+/* MD5 translation setup. Provides the APR translation handle
+ * to be used for translating the content before calculating the
+ * digest.
+ */
+APU_DECLARE(apr_status_t) apr_md5_set_xlate(apr_md5_ctx_t *context,
+ apr_xlate_t *xlate)
+{
+#if APR_HAS_XLATE
+ apr_status_t rv;
+ int is_sb;
+
+ /* TODO: remove the single-byte-only restriction from this code
+ */
+ rv = apr_xlate_sb_get(xlate, &is_sb);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ if (!is_sb) {
+ return APR_EINVAL;
+ }
+ context->xlate = xlate;
+ return APR_SUCCESS;
+#else
+ return APR_ENOTIMPL;
+#endif /* APR_HAS_XLATE */
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+ * operation, processing another message block, and updating the
+ * context.
+ */
+static apr_status_t md5_update_buffer(apr_md5_ctx_t *context,
+ const void *vinput,
+ apr_size_t inputLen,
+ int xlate_buffer)
+{
+ const unsigned char *input = vinput;
+ unsigned int i, idx, partLen;
+#if APR_HAS_XLATE
+ apr_size_t inbytes_left, outbytes_left;
+#endif
+
+ /* Compute number of bytes mod 64 */
+ idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ((context->count[0] += ((apr_uint32_t)inputLen << 3))
+ < ((apr_uint32_t)inputLen << 3))
+ context->count[1]++;
+ context->count[1] += (apr_uint32_t)inputLen >> 29;
+
+ partLen = 64 - idx;
+
+ /* Transform as many times as possible. */
+#if !APR_HAS_XLATE
+ if (inputLen >= partLen) {
+ memcpy(&context->buffer[idx], input, partLen);
+ MD5Transform(context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ MD5Transform(context->state, &input[i]);
+
+ idx = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ memcpy(&context->buffer[idx], &input[i], inputLen - i);
+#else /*APR_HAS_XLATE*/
+ if (inputLen >= partLen) {
+ if (context->xlate && (xlate_buffer == DO_XLATE)) {
+ inbytes_left = outbytes_left = partLen;
+ apr_xlate_conv_buffer(context->xlate, (const char *)input,
+ &inbytes_left,
+ (char *)&context->buffer[idx],
+ &outbytes_left);
+ }
+ else {
+ memcpy(&context->buffer[idx], input, partLen);
+ }
+ MD5Transform(context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64) {
+ if (context->xlate && (xlate_buffer == DO_XLATE)) {
+ unsigned char inp_tmp[64];
+ inbytes_left = outbytes_left = 64;
+ apr_xlate_conv_buffer(context->xlate, (const char *)&input[i],
+ &inbytes_left, (char *)inp_tmp,
+ &outbytes_left);
+ MD5Transform(context->state, inp_tmp);
+ }
+ else {
+ MD5Transform(context->state, &input[i]);
+ }
+ }
+
+ idx = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ if (context->xlate && (xlate_buffer == DO_XLATE)) {
+ inbytes_left = outbytes_left = inputLen - i;
+ apr_xlate_conv_buffer(context->xlate, (const char *)&input[i],
+ &inbytes_left, (char *)&context->buffer[idx],
+ &outbytes_left);
+ }
+ else {
+ memcpy(&context->buffer[idx], &input[i], inputLen - i);
+ }
+#endif /*APR_HAS_XLATE*/
+ return APR_SUCCESS;
+}
+
+/* MD5 block update operation. API with the default setting
+ * for EBCDIC translations
+ */
+APU_DECLARE(apr_status_t) apr_md5_update(apr_md5_ctx_t *context,
+ const void *input,
+ apr_size_t inputLen)
+{
+ return md5_update_buffer(context, input, inputLen, DO_XLATE);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+ * the message digest and zeroizing the context.
+ */
+APU_DECLARE(apr_status_t) apr_md5_final(unsigned char digest[APR_MD5_DIGESTSIZE],
+ apr_md5_ctx_t *context)
+{
+ unsigned char bits[8];
+ unsigned int idx, padLen;
+
+ /* Save number of bits */
+ Encode(bits, context->count, 8);
+
+#if APR_HAS_XLATE
+ /* apr_md5_update() should not translate for this final round. */
+ context->xlate = NULL;
+#endif /*APR_HAS_XLATE*/
+
+ /* Pad out to 56 mod 64. */
+ idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
+ padLen = (idx < 56) ? (56 - idx) : (120 - idx);
+ apr_md5_update(context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ apr_md5_update(context, bits, 8);
+
+ /* Store state in digest */
+ Encode(digest, context->state, APR_MD5_DIGESTSIZE);
+
+ /* Zeroize sensitive information. */
+ memset(context, 0, sizeof(*context));
+
+ return APR_SUCCESS;
+}
+
+/* MD5 in one step (init, update, final)
+ */
+APU_DECLARE(apr_status_t) apr_md5(unsigned char digest[APR_MD5_DIGESTSIZE],
+ const void *_input,
+ apr_size_t inputLen)
+{
+ const unsigned char *input = _input;
+ apr_md5_ctx_t ctx;
+ apr_status_t rv;
+
+ apr_md5_init(&ctx);
+
+ if ((rv = apr_md5_update(&ctx, input, inputLen)) != APR_SUCCESS)
+ return rv;
+
+ return apr_md5_final(digest, &ctx);
+}
+
+/* MD5 basic transformation. Transforms state based on block. */
+static void MD5Transform(apr_uint32_t state[4], const unsigned char block[64])
+{
+ apr_uint32_t a = state[0], b = state[1], c = state[2], d = state[3],
+ tmpbuf[APR_MD5_DIGESTSIZE];
+ const apr_uint32_t *x;
+
+#if !APR_IS_BIGENDIAN
+ if ((apr_uintptr_t)block % sizeof(apr_uint32_t) == 0) {
+ x = (apr_uint32_t *)block;
+ } else
+#endif
+ {
+ Decode(tmpbuf, block, 64);
+ x = tmpbuf;
+ }
+
+ /* Round 1 */
+ FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
+ FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
+ FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
+ FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
+ FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
+ FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
+ FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
+ FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
+ FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
+ FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
+ FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
+ GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
+ GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
+ GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
+ GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
+ GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
+ GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
+ GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
+ GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
+ GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
+ GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
+ HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
+ HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
+ HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
+ HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
+ HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
+ HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
+ HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
+ HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
+ HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
+ II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
+ II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
+ II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
+ II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
+ II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
+ II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
+ II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
+ II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
+ II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+#if !APR_IS_BIGENDIAN
+ if (x == tmpbuf)
+#endif
+ {
+ /* Zeroize sensitive information. */
+ memset(tmpbuf, 0, sizeof(tmpbuf));
+ }
+}
+
+/* Encodes input (apr_uint32_t) into output (unsigned char). Assumes len is
+ * a multiple of 4.
+ */
+static void Encode(unsigned char *output, const apr_uint32_t *input,
+ unsigned int len)
+{
+ unsigned int i, j;
+ apr_uint32_t k;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ k = input[i];
+ output[j] = (unsigned char)(k & 0xff);
+ output[j + 1] = (unsigned char)((k >> 8) & 0xff);
+ output[j + 2] = (unsigned char)((k >> 16) & 0xff);
+ output[j + 3] = (unsigned char)((k >> 24) & 0xff);
+ }
+}
+
+/* Decodes input (unsigned char) into output (apr_uint32_t). Assumes len is
+ * a multiple of 4.
+ */
+static void Decode(apr_uint32_t *output, const unsigned char *input,
+ unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((apr_uint32_t)input[j]) |
+ (((apr_uint32_t)input[j + 1]) << 8) |
+ (((apr_uint32_t)input[j + 2]) << 16) |
+ (((apr_uint32_t)input[j + 3]) << 24);
+}
+
+#if APR_CHARSET_EBCDIC
+APU_DECLARE(apr_status_t) apr_MD5InitEBCDIC(apr_xlate_t *xlate)
+{
+ xlate_ebcdic_to_ascii = xlate;
+ return APR_SUCCESS;
+}
+#endif
+
+/*
+ * Define the Magic String prefix that identifies a password as being
+ * hashed using our algorithm.
+ */
+static const char * const apr1_id = "$apr1$";
+
+/*
+ * The following MD5 password encryption code was largely borrowed from
+ * the FreeBSD 3.0 /usr/src/lib/libcrypt/crypt.c file, which is
+ * licenced as stated at the top of this file.
+ */
+
+static void to64(char *s, unsigned long v, int n)
+{
+ static unsigned char itoa64[] = /* 0 ... 63 => ASCII - 64 */
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+ while (--n >= 0) {
+ *s++ = itoa64[v&0x3f];
+ v >>= 6;
+ }
+}
+
+APU_DECLARE(apr_status_t) apr_md5_encode(const char *pw, const char *salt,
+ char *result, apr_size_t nbytes)
+{
+ /*
+ * Minimum size is 8 bytes for salt, plus 1 for the trailing NUL,
+ * plus 4 for the '$' separators, plus the password hash itself.
+ * Let's leave a goodly amount of leeway.
+ */
+
+ char passwd[120], *p;
+ const char *sp, *ep;
+ unsigned char final[APR_MD5_DIGESTSIZE];
+ apr_ssize_t sl, pl, i;
+ apr_md5_ctx_t ctx, ctx1;
+ unsigned long l;
+
+ /*
+ * Refine the salt first. It's possible we were given an already-hashed
+ * string as the salt argument, so extract the actual salt value from it
+ * if so. Otherwise just use the string up to the first '$' as the salt.
+ */
+ sp = salt;
+
+ /*
+ * If it starts with the magic string, then skip that.
+ */
+ if (!strncmp(sp, apr1_id, strlen(apr1_id))) {
+ sp += strlen(apr1_id);
+ }
+
+ /*
+ * It stops at the first '$' or 8 chars, whichever comes first
+ */
+ for (ep = sp; (*ep != '\0') && (*ep != '$') && (ep < (sp + 8)); ep++) {
+ continue;
+ }
+
+ /*
+ * Get the length of the true salt
+ */
+ sl = ep - sp;
+
+ /*
+ * 'Time to make the doughnuts..'
+ */
+ apr_md5_init(&ctx);
+#if APR_CHARSET_EBCDIC
+ apr_md5_set_xlate(&ctx, xlate_ebcdic_to_ascii);
+#endif
+
+ /*
+ * The password first, since that is what is most unknown
+ */
+ apr_md5_update(&ctx, pw, strlen(pw));
+
+ /*
+ * Then our magic string
+ */
+ apr_md5_update(&ctx, apr1_id, strlen(apr1_id));
+
+ /*
+ * Then the raw salt
+ */
+ apr_md5_update(&ctx, sp, sl);
+
+ /*
+ * Then just as many characters of the MD5(pw, salt, pw)
+ */
+ apr_md5_init(&ctx1);
+#if APR_CHARSET_EBCDIC
+ apr_md5_set_xlate(&ctx1, xlate_ebcdic_to_ascii);
+#endif
+ apr_md5_update(&ctx1, pw, strlen(pw));
+ apr_md5_update(&ctx1, sp, sl);
+ apr_md5_update(&ctx1, pw, strlen(pw));
+ apr_md5_final(final, &ctx1);
+ for (pl = strlen(pw); pl > 0; pl -= APR_MD5_DIGESTSIZE) {
+ md5_update_buffer(&ctx, final,
+ (pl > APR_MD5_DIGESTSIZE) ? APR_MD5_DIGESTSIZE : pl, SKIP_XLATE);
+ }
+
+ /*
+ * Don't leave anything around in vm they could use.
+ */
+ memset(final, 0, sizeof(final));
+
+ /*
+ * Then something really weird...
+ */
+ for (i = strlen(pw); i != 0; i >>= 1) {
+ if (i & 1) {
+ md5_update_buffer(&ctx, final, 1, SKIP_XLATE);
+ }
+ else {
+ apr_md5_update(&ctx, pw, 1);
+ }
+ }
+
+ /*
+ * Now make the output string. We know our limitations, so we
+ * can use the string routines without bounds checking.
+ */
+ strcpy(passwd, apr1_id);
+ strncat(passwd, sp, sl);
+ strcat(passwd, "$");
+
+ apr_md5_final(final, &ctx);
+
+ /*
+ * And now, just to make sure things don't run too fast..
+ * On a 60 Mhz Pentium this takes 34 msec, so you would
+ * need 30 seconds to build a 1000 entry dictionary...
+ */
+ for (i = 0; i < 1000; i++) {
+ apr_md5_init(&ctx1);
+ /*
+ * apr_md5_final clears out ctx1.xlate at the end of each loop,
+ * so need to to set it each time through
+ */
+#if APR_CHARSET_EBCDIC
+ apr_md5_set_xlate(&ctx1, xlate_ebcdic_to_ascii);
+#endif
+ if (i & 1) {
+ apr_md5_update(&ctx1, pw, strlen(pw));
+ }
+ else {
+ md5_update_buffer(&ctx1, final, APR_MD5_DIGESTSIZE, SKIP_XLATE);
+ }
+ if (i % 3) {
+ apr_md5_update(&ctx1, sp, sl);
+ }
+
+ if (i % 7) {
+ apr_md5_update(&ctx1, pw, strlen(pw));
+ }
+
+ if (i & 1) {
+ md5_update_buffer(&ctx1, final, APR_MD5_DIGESTSIZE, SKIP_XLATE);
+ }
+ else {
+ apr_md5_update(&ctx1, pw, strlen(pw));
+ }
+ apr_md5_final(final,&ctx1);
+ }
+
+ p = passwd + strlen(passwd);
+
+ l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p, l, 4); p += 4;
+ l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p, l, 4); p += 4;
+ l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p, l, 4); p += 4;
+ l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p, l, 4); p += 4;
+ l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p, l, 4); p += 4;
+ l = final[11] ; to64(p, l, 2); p += 2;
+ *p = '\0';
+
+ /*
+ * Don't leave anything around in vm they could use.
+ */
+ memset(final, 0, sizeof(final));
+
+ apr_cpystrn(result, passwd, nbytes - 1);
+ return APR_SUCCESS;
+}
diff --git a/crypto/apr_passwd.c b/crypto/apr_passwd.c
new file mode 100644
index 0000000..c961de2
--- /dev/null
+++ b/crypto/apr_passwd.c
@@ -0,0 +1,200 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+#include "apr_md5.h"
+#include "apr_lib.h"
+#include "apr_sha1.h"
+#include "apu_config.h"
+#include "crypt_blowfish.h"
+
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if APR_HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+static const char * const apr1_id = "$apr1$";
+
+#if !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
+#if defined(APU_CRYPT_THREADSAFE) || !APR_HAS_THREADS || \
+ defined(CRYPT_R_CRYPTD) || defined(CRYPT_R_STRUCT_CRYPT_DATA)
+
+#define crypt_mutex_lock()
+#define crypt_mutex_unlock()
+
+#elif APR_HAVE_PTHREAD_H && defined(PTHREAD_MUTEX_INITIALIZER)
+
+static pthread_mutex_t crypt_mutex = PTHREAD_MUTEX_INITIALIZER;
+static void crypt_mutex_lock(void)
+{
+ pthread_mutex_lock(&crypt_mutex);
+}
+
+static void crypt_mutex_unlock(void)
+{
+ pthread_mutex_unlock(&crypt_mutex);
+}
+
+#else
+
+#error apr_password_validate() is not threadsafe. rebuild APR without thread support.
+
+#endif
+#endif
+
+#if defined(WIN32) || defined(BEOS) || defined(NETWARE) || defined(__ANDROID__)
+#define CRYPT_MISSING 1
+#else
+#define CRYPT_MISSING 0
+#endif
+
+/*
+ * Validate a plaintext password against a smashed one. Uses either
+ * crypt() (if available) or apr_md5_encode() or apr_sha1_base64(), depending
+ * upon the format of the smashed input password. Returns APR_SUCCESS if
+ * they match, or APR_EMISMATCH if they don't. If the platform doesn't
+ * support crypt, then the default check is against a clear text string.
+ */
+APU_DECLARE(apr_status_t) apr_password_validate(const char *passwd,
+ const char *hash)
+{
+ char sample[200];
+#if !CRYPT_MISSING
+ char *crypt_pw;
+#endif
+ if (hash[0] == '$'
+ && hash[1] == '2'
+ && (hash[2] == 'a' || hash[2] == 'y')
+ && hash[3] == '$') {
+ if (_crypt_blowfish_rn(passwd, hash, sample, sizeof(sample)) == NULL)
+ return APR_FROM_OS_ERROR(errno);
+ }
+ else if (!strncmp(hash, apr1_id, strlen(apr1_id))) {
+ /*
+ * The hash was created using our custom algorithm.
+ */
+ apr_md5_encode(passwd, hash, sample, sizeof(sample));
+ }
+ else if (!strncmp(hash, APR_SHA1PW_ID, APR_SHA1PW_IDLEN)) {
+ apr_sha1_base64(passwd, (int)strlen(passwd), sample);
+ }
+ else {
+ /*
+ * It's not our algorithm, so feed it to crypt() if possible.
+ */
+#if CRYPT_MISSING
+ return (strcmp(passwd, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
+#elif defined(CRYPT_R_CRYPTD)
+ apr_status_t rv;
+ CRYPTD *buffer = malloc(sizeof(*buffer));
+
+ if (buffer == NULL)
+ return APR_ENOMEM;
+ crypt_pw = crypt_r(passwd, hash, buffer);
+ if (!crypt_pw)
+ rv = APR_EMISMATCH;
+ else
+ rv = (strcmp(crypt_pw, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
+ free(buffer);
+ return rv;
+#elif defined(CRYPT_R_STRUCT_CRYPT_DATA)
+ apr_status_t rv;
+ struct crypt_data *buffer = malloc(sizeof(*buffer));
+
+ if (buffer == NULL)
+ return APR_ENOMEM;
+
+#ifdef __GLIBC_PREREQ
+ /*
+ * For not too old glibc (>= 2.3.2), it's enough to set
+ * buffer.initialized = 0. For < 2.3.2 and for other platforms,
+ * we need to zero the whole struct.
+ */
+#if __GLIBC_PREREQ(2,4)
+#define USE_CRYPT_DATA_INITALIZED
+#endif
+#endif
+
+#ifdef USE_CRYPT_DATA_INITALIZED
+ buffer->initialized = 0;
+#else
+ memset(buffer, 0, sizeof(*buffer));
+#endif
+
+ crypt_pw = crypt_r(passwd, hash, buffer);
+ if (!crypt_pw)
+ rv = APR_EMISMATCH;
+ else
+ rv = (strcmp(crypt_pw, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
+ free(buffer);
+ return rv;
+#else
+ /* Do a bit of sanity checking since we know that crypt_r()
+ * should always be used for threaded builds on AIX, and
+ * problems in configure logic can result in the wrong
+ * choice being made.
+ */
+#if defined(_AIX) && APR_HAS_THREADS
+#error Configuration error! crypt_r() should have been selected!
+#endif
+ {
+ apr_status_t rv;
+
+ /* Handle thread safety issues by holding a mutex around the
+ * call to crypt().
+ */
+ crypt_mutex_lock();
+ crypt_pw = crypt(passwd, hash);
+ if (!crypt_pw) {
+ rv = APR_EMISMATCH;
+ }
+ else {
+ rv = (strcmp(crypt_pw, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
+ }
+ crypt_mutex_unlock();
+ return rv;
+ }
+#endif
+ }
+ return (strcmp(sample, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
+}
+
+static const char * const bcrypt_id = "$2y$";
+APU_DECLARE(apr_status_t) apr_bcrypt_encode(const char *pw,
+ unsigned int count,
+ const unsigned char *salt,
+ apr_size_t salt_len,
+ char *out, apr_size_t out_len)
+{
+ char setting[40];
+ if (_crypt_gensalt_blowfish_rn(bcrypt_id, count, (const char *)salt,
+ salt_len, setting, sizeof(setting)) == NULL)
+ return APR_FROM_OS_ERROR(errno);
+ if (_crypt_blowfish_rn(pw, setting, out, out_len) == NULL)
+ return APR_FROM_OS_ERROR(errno);
+ return APR_SUCCESS;
+}
diff --git a/crypto/apr_sha1.c b/crypto/apr_sha1.c
new file mode 100644
index 0000000..8959ffc
--- /dev/null
+++ b/crypto/apr_sha1.c
@@ -0,0 +1,368 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * The exported function:
+ *
+ * apr_sha1_base64(const char *clear, int len, char *out);
+ *
+ * provides a means to SHA1 crypt/encode a plaintext password in
+ * a way which makes password files compatible with those commonly
+ * used in netscape web and ldap installations. It was put together
+ * by Clinton Wong <clintdw@netcom.com>, who also notes that:
+ *
+ * Note: SHA1 support is useful for migration purposes, but is less
+ * secure than Apache's password format, since Apache's (MD5)
+ * password format uses a random eight character salt to generate
+ * one of many possible hashes for the same password. Netscape
+ * uses plain SHA1 without a salt, so the same password
+ * will always generate the same hash, making it easier
+ * to break since the search space is smaller.
+ *
+ * See also the documentation in support/SHA1 as to hints on how to
+ * migrate an existing netscape installation and other supplied utitlites.
+ *
+ * This software also makes use of the following component:
+ *
+ * NIST Secure Hash Algorithm
+ * heavily modified by Uwe Hollerbach uh@alumni.caltech edu
+ * from Peter C. Gutmann's implementation as found in
+ * Applied Cryptography by Bruce Schneier
+ * This code is hereby placed in the public domain
+ */
+
+#include "apr_sha1.h"
+#include "apr_base64.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+#if APR_CHARSET_EBCDIC
+#include "apr_xlate.h"
+#endif /*APR_CHARSET_EBCDIC*/
+#include <string.h>
+
+/* a bit faster & bigger, if defined */
+#define UNROLL_LOOPS
+
+/* NIST's proposed modification to SHA, 7/11/94 */
+#define USE_MODIFIED_SHA
+
+/* SHA f()-functions */
+#define f1(x,y,z) ((x & y) | (~x & z))
+#define f2(x,y,z) (x ^ y ^ z)
+#define f3(x,y,z) ((x & y) | (x & z) | (y & z))
+#define f4(x,y,z) (x ^ y ^ z)
+
+/* SHA constants */
+#define CONST1 0x5a827999L
+#define CONST2 0x6ed9eba1L
+#define CONST3 0x8f1bbcdcL
+#define CONST4 0xca62c1d6L
+
+/* 32-bit rotate */
+
+#define ROT32(x,n) ((x << n) | (x >> (32 - n)))
+
+#define FUNC(n,i) \
+ temp = ROT32(A,5) + f##n(B,C,D) + E + W[i] + CONST##n; \
+ E = D; D = C; C = ROT32(B,30); B = A; A = temp
+
+#define SHA_BLOCKSIZE 64
+
+#if APR_CHARSET_EBCDIC
+static apr_xlate_t *ebcdic2ascii_xlate;
+
+APU_DECLARE(apr_status_t) apr_SHA1InitEBCDIC(apr_xlate_t *x)
+{
+ apr_status_t rv;
+ int onoff;
+
+ /* Only single-byte conversion is supported.
+ */
+ rv = apr_xlate_sb_get(x, &onoff);
+ if (rv) {
+ return rv;
+ }
+ if (!onoff) { /* If conversion is not single-byte-only */
+ return APR_EINVAL;
+ }
+ ebcdic2ascii_xlate = x;
+ return APR_SUCCESS;
+}
+#endif
+
+/* do SHA transformation */
+static void sha_transform(apr_sha1_ctx_t *sha_info)
+{
+ int i;
+ apr_uint32_t temp, A, B, C, D, E, W[80];
+
+ for (i = 0; i < 16; ++i) {
+ W[i] = sha_info->data[i];
+ }
+ for (i = 16; i < 80; ++i) {
+ W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
+#ifdef USE_MODIFIED_SHA
+ W[i] = ROT32(W[i], 1);
+#endif /* USE_MODIFIED_SHA */
+ }
+ A = sha_info->digest[0];
+ B = sha_info->digest[1];
+ C = sha_info->digest[2];
+ D = sha_info->digest[3];
+ E = sha_info->digest[4];
+#ifdef UNROLL_LOOPS
+ FUNC(1, 0); FUNC(1, 1); FUNC(1, 2); FUNC(1, 3); FUNC(1, 4);
+ FUNC(1, 5); FUNC(1, 6); FUNC(1, 7); FUNC(1, 8); FUNC(1, 9);
+ FUNC(1,10); FUNC(1,11); FUNC(1,12); FUNC(1,13); FUNC(1,14);
+ FUNC(1,15); FUNC(1,16); FUNC(1,17); FUNC(1,18); FUNC(1,19);
+
+ FUNC(2,20); FUNC(2,21); FUNC(2,22); FUNC(2,23); FUNC(2,24);
+ FUNC(2,25); FUNC(2,26); FUNC(2,27); FUNC(2,28); FUNC(2,29);
+ FUNC(2,30); FUNC(2,31); FUNC(2,32); FUNC(2,33); FUNC(2,34);
+ FUNC(2,35); FUNC(2,36); FUNC(2,37); FUNC(2,38); FUNC(2,39);
+
+ FUNC(3,40); FUNC(3,41); FUNC(3,42); FUNC(3,43); FUNC(3,44);
+ FUNC(3,45); FUNC(3,46); FUNC(3,47); FUNC(3,48); FUNC(3,49);
+ FUNC(3,50); FUNC(3,51); FUNC(3,52); FUNC(3,53); FUNC(3,54);
+ FUNC(3,55); FUNC(3,56); FUNC(3,57); FUNC(3,58); FUNC(3,59);
+
+ FUNC(4,60); FUNC(4,61); FUNC(4,62); FUNC(4,63); FUNC(4,64);
+ FUNC(4,65); FUNC(4,66); FUNC(4,67); FUNC(4,68); FUNC(4,69);
+ FUNC(4,70); FUNC(4,71); FUNC(4,72); FUNC(4,73); FUNC(4,74);
+ FUNC(4,75); FUNC(4,76); FUNC(4,77); FUNC(4,78); FUNC(4,79);
+#else /* !UNROLL_LOOPS */
+ for (i = 0; i < 20; ++i) {
+ FUNC(1,i);
+ }
+ for (i = 20; i < 40; ++i) {
+ FUNC(2,i);
+ }
+ for (i = 40; i < 60; ++i) {
+ FUNC(3,i);
+ }
+ for (i = 60; i < 80; ++i) {
+ FUNC(4,i);
+ }
+#endif /* !UNROLL_LOOPS */
+ sha_info->digest[0] += A;
+ sha_info->digest[1] += B;
+ sha_info->digest[2] += C;
+ sha_info->digest[3] += D;
+ sha_info->digest[4] += E;
+}
+
+union endianTest {
+ long Long;
+ char Char[sizeof(long)];
+};
+
+static char isLittleEndian(void)
+{
+ static union endianTest u;
+ u.Long = 1;
+ return (u.Char[0] == 1);
+}
+
+/* change endianness of data */
+
+/* count is the number of bytes to do an endian flip */
+static void maybe_byte_reverse(apr_uint32_t *buffer, int count)
+{
+ int i;
+ apr_byte_t ct[4], *cp;
+
+ if (isLittleEndian()) { /* do the swap only if it is little endian */
+ count /= sizeof(apr_uint32_t);
+ cp = (apr_byte_t *) buffer;
+ for (i = 0; i < count; ++i) {
+ ct[0] = cp[0];
+ ct[1] = cp[1];
+ ct[2] = cp[2];
+ ct[3] = cp[3];
+ cp[0] = ct[3];
+ cp[1] = ct[2];
+ cp[2] = ct[1];
+ cp[3] = ct[0];
+ cp += sizeof(apr_uint32_t);
+ }
+ }
+}
+
+/* initialize the SHA digest */
+
+APU_DECLARE(void) apr_sha1_init(apr_sha1_ctx_t *sha_info)
+{
+ sha_info->digest[0] = 0x67452301L;
+ sha_info->digest[1] = 0xefcdab89L;
+ sha_info->digest[2] = 0x98badcfeL;
+ sha_info->digest[3] = 0x10325476L;
+ sha_info->digest[4] = 0xc3d2e1f0L;
+ sha_info->count_lo = 0L;
+ sha_info->count_hi = 0L;
+ sha_info->local = 0;
+}
+
+/* update the SHA digest */
+
+APU_DECLARE(void) apr_sha1_update_binary(apr_sha1_ctx_t *sha_info,
+ const unsigned char *buffer,
+ unsigned int count)
+{
+ unsigned int i;
+
+ if ((sha_info->count_lo + ((apr_uint32_t) count << 3)) < sha_info->count_lo) {
+ ++sha_info->count_hi;
+ }
+ sha_info->count_lo += (apr_uint32_t) count << 3;
+ sha_info->count_hi += (apr_uint32_t) count >> 29;
+ if (sha_info->local) {
+ i = SHA_BLOCKSIZE - sha_info->local;
+ if (i > count) {
+ i = count;
+ }
+ memcpy(((apr_byte_t *) sha_info->data) + sha_info->local, buffer, i);
+ count -= i;
+ buffer += i;
+ sha_info->local += i;
+ if (sha_info->local == SHA_BLOCKSIZE) {
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ }
+ else {
+ return;
+ }
+ }
+ while (count >= SHA_BLOCKSIZE) {
+ memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
+ buffer += SHA_BLOCKSIZE;
+ count -= SHA_BLOCKSIZE;
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ }
+ memcpy(sha_info->data, buffer, count);
+ sha_info->local = count;
+}
+
+APU_DECLARE(void) apr_sha1_update(apr_sha1_ctx_t *sha_info, const char *buf,
+ unsigned int count)
+{
+#if APR_CHARSET_EBCDIC
+ int i;
+ const apr_byte_t *buffer = (const apr_byte_t *) buf;
+ apr_size_t inbytes_left, outbytes_left;
+
+ if ((sha_info->count_lo + ((apr_uint32_t) count << 3)) < sha_info->count_lo) {
+ ++sha_info->count_hi;
+ }
+ sha_info->count_lo += (apr_uint32_t) count << 3;
+ sha_info->count_hi += (apr_uint32_t) count >> 29;
+ /* Is there a remainder of the previous Update operation? */
+ if (sha_info->local) {
+ i = SHA_BLOCKSIZE - sha_info->local;
+ if (i > count) {
+ i = count;
+ }
+ inbytes_left = outbytes_left = i;
+ apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left,
+ ((apr_byte_t *) sha_info->data) + sha_info->local,
+ &outbytes_left);
+ count -= i;
+ buffer += i;
+ sha_info->local += i;
+ if (sha_info->local == SHA_BLOCKSIZE) {
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ }
+ else {
+ return;
+ }
+ }
+ while (count >= SHA_BLOCKSIZE) {
+ inbytes_left = outbytes_left = SHA_BLOCKSIZE;
+ apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left,
+ (apr_byte_t *) sha_info->data, &outbytes_left);
+ buffer += SHA_BLOCKSIZE;
+ count -= SHA_BLOCKSIZE;
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ }
+ inbytes_left = outbytes_left = count;
+ apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left,
+ (apr_byte_t *) sha_info->data, &outbytes_left);
+ sha_info->local = count;
+#else
+ apr_sha1_update_binary(sha_info, (const unsigned char *) buf, count);
+#endif
+}
+
+/* finish computing the SHA digest */
+
+APU_DECLARE(void) apr_sha1_final(unsigned char digest[APR_SHA1_DIGESTSIZE],
+ apr_sha1_ctx_t *sha_info)
+{
+ int count, i, j;
+ apr_uint32_t lo_bit_count, hi_bit_count, k;
+
+ lo_bit_count = sha_info->count_lo;
+ hi_bit_count = sha_info->count_hi;
+ count = (int) ((lo_bit_count >> 3) & 0x3f);
+ ((apr_byte_t *) sha_info->data)[count++] = 0x80;
+ if (count > SHA_BLOCKSIZE - 8) {
+ memset(((apr_byte_t *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ memset((apr_byte_t *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
+ }
+ else {
+ memset(((apr_byte_t *) sha_info->data) + count, 0,
+ SHA_BLOCKSIZE - 8 - count);
+ }
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_info->data[14] = hi_bit_count;
+ sha_info->data[15] = lo_bit_count;
+ sha_transform(sha_info);
+
+ for (i = 0, j = 0; j < APR_SHA1_DIGESTSIZE; i++) {
+ k = sha_info->digest[i];
+ digest[j++] = (unsigned char) ((k >> 24) & 0xff);
+ digest[j++] = (unsigned char) ((k >> 16) & 0xff);
+ digest[j++] = (unsigned char) ((k >> 8) & 0xff);
+ digest[j++] = (unsigned char) (k & 0xff);
+ }
+}
+
+
+APU_DECLARE(void) apr_sha1_base64(const char *clear, int len, char *out)
+{
+ int l;
+ apr_sha1_ctx_t context;
+ apr_byte_t digest[APR_SHA1_DIGESTSIZE];
+
+ apr_sha1_init(&context);
+ apr_sha1_update(&context, clear, len);
+ apr_sha1_final(digest, &context);
+
+ /* private marker. */
+ apr_cpystrn(out, APR_SHA1PW_ID, APR_SHA1PW_IDLEN + 1);
+
+ /* SHA1 hash is always 20 chars */
+ l = apr_base64_encode_binary(out + APR_SHA1PW_IDLEN, digest, sizeof(digest));
+ out[l + APR_SHA1PW_IDLEN] = '\0';
+
+ /*
+ * output of base64 encoded SHA1 is always 28 chars + APR_SHA1PW_IDLEN
+ */
+}
diff --git a/crypto/apr_siphash.c b/crypto/apr_siphash.c
new file mode 100644
index 0000000..c9cabe2
--- /dev/null
+++ b/crypto/apr_siphash.c
@@ -0,0 +1,196 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * SipHash (C reference implementation, APR-ized), originating from:
+ * https://131002.net/siphash/siphash24.c.
+ */
+
+#include "apr_siphash.h"
+
+#define ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
+
+#define U8TO64_LE(p) \
+ (((apr_uint64_t)((p)[0]) ) | \
+ ((apr_uint64_t)((p)[1]) << 8) | \
+ ((apr_uint64_t)((p)[2]) << 16) | \
+ ((apr_uint64_t)((p)[3]) << 24) | \
+ ((apr_uint64_t)((p)[4]) << 32) | \
+ ((apr_uint64_t)((p)[5]) << 40) | \
+ ((apr_uint64_t)((p)[6]) << 48) | \
+ ((apr_uint64_t)((p)[7]) << 56))
+
+#define U64TO8_LE(p, v) \
+do { \
+ (p)[0] = (unsigned char)((v) ); \
+ (p)[1] = (unsigned char)((v) >> 8); \
+ (p)[2] = (unsigned char)((v) >> 16); \
+ (p)[3] = (unsigned char)((v) >> 24); \
+ (p)[4] = (unsigned char)((v) >> 32); \
+ (p)[5] = (unsigned char)((v) >> 40); \
+ (p)[6] = (unsigned char)((v) >> 48); \
+ (p)[7] = (unsigned char)((v) >> 56); \
+} while (0)
+
+#define SIPROUND() \
+do { \
+ v0 += v1; v1=ROTL64(v1,13); v1 ^= v0; v0=ROTL64(v0,32); \
+ v2 += v3; v3=ROTL64(v3,16); v3 ^= v2; \
+ v0 += v3; v3=ROTL64(v3,21); v3 ^= v0; \
+ v2 += v1; v1=ROTL64(v1,17); v1 ^= v2; v2=ROTL64(v2,32); \
+} while(0)
+
+#define SIPHASH(r, s, n, k) \
+do { \
+ const unsigned char *ptr, *end; \
+ apr_uint64_t v0, v1, v2, v3, m; \
+ apr_uint64_t k0, k1; \
+ unsigned int rem; \
+ \
+ k0 = U8TO64_LE(k + 0); \
+ k1 = U8TO64_LE(k + 8); \
+ v3 = k1 ^ (apr_uint64_t)0x7465646279746573ULL; \
+ v2 = k0 ^ (apr_uint64_t)0x6c7967656e657261ULL; \
+ v1 = k1 ^ (apr_uint64_t)0x646f72616e646f6dULL; \
+ v0 = k0 ^ (apr_uint64_t)0x736f6d6570736575ULL; \
+ \
+ rem = (unsigned int)(n & 0x7); \
+ for (ptr = s, end = ptr + n - rem; ptr < end; ptr += 8) { \
+ m = U8TO64_LE(ptr); \
+ v3 ^= m; \
+ cROUNDS \
+ v0 ^= m; \
+ } \
+ m = (apr_uint64_t)(n & 0xff) << 56; \
+ switch (rem) { \
+ case 7: m |= (apr_uint64_t)ptr[6] << 48; \
+ case 6: m |= (apr_uint64_t)ptr[5] << 40; \
+ case 5: m |= (apr_uint64_t)ptr[4] << 32; \
+ case 4: m |= (apr_uint64_t)ptr[3] << 24; \
+ case 3: m |= (apr_uint64_t)ptr[2] << 16; \
+ case 2: m |= (apr_uint64_t)ptr[1] << 8; \
+ case 1: m |= (apr_uint64_t)ptr[0]; \
+ case 0: break; \
+ } \
+ v3 ^= m; \
+ cROUNDS \
+ v0 ^= m; \
+ \
+ v2 ^= 0xff; \
+ dROUNDS \
+ \
+ r = v0 ^ v1 ^ v2 ^ v3; \
+} while (0)
+
+APU_DECLARE(apr_uint64_t) apr_siphash(const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE],
+ unsigned int c, unsigned int d)
+{
+ apr_uint64_t h;
+ unsigned int i;
+
+#undef cROUNDS
+#define cROUNDS \
+ for (i = 0; i < c; ++i) { \
+ SIPROUND(); \
+ }
+
+#undef dROUNDS
+#define dROUNDS \
+ for (i = 0; i < d; ++i) { \
+ SIPROUND(); \
+ }
+
+ SIPHASH(h, src, len, key);
+ return h;
+}
+
+APU_DECLARE(void) apr_siphash_auth(unsigned char out[APR_SIPHASH_DSIZE],
+ const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE],
+ unsigned int c, unsigned int d)
+{
+ apr_uint64_t h;
+ h = apr_siphash(src, len, key, c, d);
+ U64TO8_LE(out, h);
+}
+
+APU_DECLARE(apr_uint64_t) apr_siphash24(const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE])
+{
+ apr_uint64_t h;
+
+#undef cROUNDS
+#define cROUNDS \
+ SIPROUND(); \
+ SIPROUND();
+
+#undef dROUNDS
+#define dROUNDS \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND();
+
+ SIPHASH(h, src, len, key);
+ return h;
+}
+
+APU_DECLARE(void) apr_siphash24_auth(unsigned char out[APR_SIPHASH_DSIZE],
+ const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE])
+{
+ apr_uint64_t h;
+ h = apr_siphash24(src, len, key);
+ U64TO8_LE(out, h);
+}
+
+APU_DECLARE(apr_uint64_t) apr_siphash48(const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE])
+{
+ apr_uint64_t h;
+
+#undef cROUNDS
+#define cROUNDS \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND();
+
+#undef dROUNDS
+#define dROUNDS \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND();
+
+ SIPHASH(h, src, len, key);
+ return h;
+}
+
+APU_DECLARE(void) apr_siphash48_auth(unsigned char out[APR_SIPHASH_DSIZE],
+ const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE])
+{
+ apr_uint64_t h;
+ h = apr_siphash48(src, len, key);
+ U64TO8_LE(out, h);
+}
+
diff --git a/crypto/crypt_blowfish.c b/crypto/crypt_blowfish.c
new file mode 100644
index 0000000..3d306cf
--- /dev/null
+++ b/crypto/crypt_blowfish.c
@@ -0,0 +1,902 @@
+/*
+ * The crypt_blowfish homepage is:
+ *
+ * http://www.openwall.com/crypt/
+ *
+ * This code comes from John the Ripper password cracker, with reentrant
+ * and crypt(3) interfaces added, but optimizations specific to password
+ * cracking removed.
+ *
+ * Written by Solar Designer <solar at openwall.com> in 1998-2011.
+ * No copyright is claimed, and the software is hereby placed in the public
+ * domain. In case this attempt to disclaim copyright and place the software
+ * in the public domain is deemed null and void, then the software is
+ * Copyright (c) 1998-2011 Solar Designer and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * It is my intent that you should be able to use this on your system,
+ * as part of a software package, or anywhere else to improve security,
+ * ensure compatibility, or for any other purpose. I would appreciate
+ * it if you give credit where it is due and keep your modifications in
+ * the public domain as well, but I don't require that in order to let
+ * you place this code and any modifications you make under a license
+ * of your choice.
+ *
+ * This implementation is mostly compatible with OpenBSD's bcrypt.c (prefix
+ * "$2a$") by Niels Provos <provos at citi.umich.edu>, and uses some of his
+ * ideas. The password hashing algorithm was designed by David Mazieres
+ * <dm at lcs.mit.edu>. For more information on the level of compatibility,
+ * prefer refer to the comments in BF_set_key() below and to the included
+ * crypt(3) man page.
+ *
+ * There's a paper on the algorithm that explains its design decisions:
+ *
+ * http://www.usenix.org/events/usenix99/provos.html
+ *
+ * Some of the tricks in BF_ROUND might be inspired by Eric Young's
+ * Blowfish library (I can't be sure if I would think of something if I
+ * hadn't seen his code).
+ */
+
+#include <string.h>
+
+#include <errno.h>
+#ifndef __set_errno
+#define __set_errno(val) errno = (val)
+#endif
+
+/* Just to make sure the prototypes match the actual definitions */
+#include "crypt_blowfish.h"
+
+#ifdef __i386__
+#define BF_ASM 0
+#define BF_SCALE 1
+#elif defined(__x86_64__) || defined(__alpha__) || defined(__hppa__)
+#define BF_ASM 0
+#define BF_SCALE 1
+#else
+#define BF_ASM 0
+#define BF_SCALE 0
+#endif
+
+typedef unsigned int BF_word;
+typedef signed int BF_word_signed;
+
+/* Number of Blowfish rounds, this is also hardcoded into a few places */
+#define BF_N 16
+
+typedef BF_word BF_key[BF_N + 2];
+
+typedef struct {
+ BF_word S[4][0x100];
+ BF_key P;
+} BF_ctx;
+
+/*
+ * Magic IV for 64 Blowfish encryptions that we do at the end.
+ * The string is "OrpheanBeholderScryDoubt" on big-endian.
+ */
+static BF_word BF_magic_w[6] = {
+ 0x4F727068, 0x65616E42, 0x65686F6C,
+ 0x64657253, 0x63727944, 0x6F756274
+};
+
+/*
+ * P-box and S-box tables initialized with digits of Pi.
+ */
+static BF_ctx BF_init_state = {
+ {
+ {
+ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+ 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+ 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+ 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+ 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
+ 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
+ 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+ 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+ 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+ 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
+ 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
+ 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+ 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+ 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+ 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
+ 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
+ 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+ 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+ 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+ 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
+ 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
+ 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
+ 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+ 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+ 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
+ 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
+ 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+ 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+ 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+ 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
+ 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
+ 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
+ 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+ 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+ 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
+ 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
+ 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
+ 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+ 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+ 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
+ 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
+ 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+ 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+ 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+ 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
+ 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
+ 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+ 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+ 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+ 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
+ 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+ 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+ 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+ 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
+ }, {
+ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
+ 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+ 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+ 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
+ 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
+ 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+ 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
+ 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
+ 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+ 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
+ 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
+ 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+ 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
+ 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+ 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+ 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
+ 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
+ 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+ 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
+ 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
+ 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+ 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
+ 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
+ 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+ 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
+ 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
+ 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+ 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
+ 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
+ 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
+ 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
+ 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+ 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
+ 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
+ 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+ 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
+ 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
+ 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+ 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
+ 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
+ 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+ 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
+ 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
+ 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+ 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
+ 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
+ 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+ 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
+ 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
+ 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+ 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
+ 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
+ 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+ 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
+ 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
+ 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+ 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
+ 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
+ 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
+ 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+ 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+ 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
+ }, {
+ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
+ 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+ 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+ 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+ 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
+ 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+ 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
+ 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+ 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+ 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
+ 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
+ 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+ 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
+ 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+ 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+ 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
+ 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
+ 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+ 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
+ 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+ 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+ 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+ 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
+ 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+ 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
+ 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+ 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+ 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
+ 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
+ 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+ 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
+ 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+ 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+ 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
+ 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
+ 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+ 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
+ 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+ 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+ 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+ 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
+ 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+ 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
+ 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+ 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+ 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
+ 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
+ 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+ 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
+ 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
+ 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+ 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
+ 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
+ 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+ 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
+ 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+ 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+ 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+ 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
+ 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+ 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
+ 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+ 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+ 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
+ }, {
+ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
+ 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+ 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+ 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+ 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
+ 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+ 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
+ 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
+ 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+ 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
+ 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
+ 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+ 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
+ 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
+ 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+ 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
+ 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
+ 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+ 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
+ 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
+ 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+ 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+ 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
+ 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+ 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
+ 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
+ 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+ 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
+ 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
+ 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+ 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
+ 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
+ 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+ 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
+ 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
+ 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
+ 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
+ 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+ 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
+ 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
+ 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
+ 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
+ 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+ 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+ 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
+ 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+ 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
+ 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
+ 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+ 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
+ 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
+ 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+ 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
+ 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
+ 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+ 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
+ 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
+ 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
+ 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+ 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+ 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
+ }
+ }, {
+ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
+ 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
+ 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
+ 0x9216d5d9, 0x8979fb1b
+ }
+};
+
+static unsigned char BF_itoa64[64 + 1] =
+ "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+static unsigned char BF_atoi64[0x60] = {
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64,
+ 64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64,
+ 64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64
+};
+
+#define BF_safe_atoi64(dst, src) \
+{ \
+ tmp = (unsigned char)(src); \
+ if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \
+ tmp = BF_atoi64[tmp]; \
+ if (tmp > 63) return -1; \
+ (dst) = tmp; \
+}
+
+static int BF_decode(BF_word *dst, const char *src, int size)
+{
+ unsigned char *dptr = (unsigned char *)dst;
+ unsigned char *end = dptr + size;
+ const unsigned char *sptr = (const unsigned char *)src;
+ unsigned int tmp, c1, c2, c3, c4;
+
+ do {
+ BF_safe_atoi64(c1, *sptr++);
+ BF_safe_atoi64(c2, *sptr++);
+ *dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);
+ if (dptr >= end) break;
+
+ BF_safe_atoi64(c3, *sptr++);
+ *dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2);
+ if (dptr >= end) break;
+
+ BF_safe_atoi64(c4, *sptr++);
+ *dptr++ = ((c3 & 0x03) << 6) | c4;
+ } while (dptr < end);
+
+ return 0;
+}
+
+static void BF_encode(char *dst, const BF_word *src, int size)
+{
+ const unsigned char *sptr = (const unsigned char *)src;
+ const unsigned char *end = sptr + size;
+ unsigned char *dptr = (unsigned char *)dst;
+ unsigned int c1, c2;
+
+ do {
+ c1 = *sptr++;
+ *dptr++ = BF_itoa64[c1 >> 2];
+ c1 = (c1 & 0x03) << 4;
+ if (sptr >= end) {
+ *dptr++ = BF_itoa64[c1];
+ break;
+ }
+
+ c2 = *sptr++;
+ c1 |= c2 >> 4;
+ *dptr++ = BF_itoa64[c1];
+ c1 = (c2 & 0x0f) << 2;
+ if (sptr >= end) {
+ *dptr++ = BF_itoa64[c1];
+ break;
+ }
+
+ c2 = *sptr++;
+ c1 |= c2 >> 6;
+ *dptr++ = BF_itoa64[c1];
+ *dptr++ = BF_itoa64[c2 & 0x3f];
+ } while (sptr < end);
+}
+
+static void BF_swap(BF_word *x, int count)
+{
+ static int endianness_check = 1;
+ char *is_little_endian = (char *)&endianness_check;
+ BF_word tmp;
+
+ if (*is_little_endian)
+ do {
+ tmp = *x;
+ tmp = (tmp << 16) | (tmp >> 16);
+ *x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF);
+ } while (--count);
+}
+
+#if BF_SCALE
+/* Architectures which can shift addresses left by 2 bits with no extra cost */
+#define BF_ROUND(L, R, N) \
+ tmp1 = L & 0xFF; \
+ tmp2 = L >> 8; \
+ tmp2 &= 0xFF; \
+ tmp3 = L >> 16; \
+ tmp3 &= 0xFF; \
+ tmp4 = L >> 24; \
+ tmp1 = data.ctx.S[3][tmp1]; \
+ tmp2 = data.ctx.S[2][tmp2]; \
+ tmp3 = data.ctx.S[1][tmp3]; \
+ tmp3 += data.ctx.S[0][tmp4]; \
+ tmp3 ^= tmp2; \
+ R ^= data.ctx.P[N + 1]; \
+ tmp3 += tmp1; \
+ R ^= tmp3;
+#else
+/* Architectures with no complicated addressing modes supported */
+#define BF_INDEX(S, i) \
+ (*((BF_word *)(((unsigned char *)S) + (i))))
+#define BF_ROUND(L, R, N) \
+ tmp1 = L & 0xFF; \
+ tmp1 <<= 2; \
+ tmp2 = L >> 6; \
+ tmp2 &= 0x3FC; \
+ tmp3 = L >> 14; \
+ tmp3 &= 0x3FC; \
+ tmp4 = L >> 22; \
+ tmp4 &= 0x3FC; \
+ tmp1 = BF_INDEX(data.ctx.S[3], tmp1); \
+ tmp2 = BF_INDEX(data.ctx.S[2], tmp2); \
+ tmp3 = BF_INDEX(data.ctx.S[1], tmp3); \
+ tmp3 += BF_INDEX(data.ctx.S[0], tmp4); \
+ tmp3 ^= tmp2; \
+ R ^= data.ctx.P[N + 1]; \
+ tmp3 += tmp1; \
+ R ^= tmp3;
+#endif
+
+/*
+ * Encrypt one block, BF_N is hardcoded here.
+ */
+#define BF_ENCRYPT \
+ L ^= data.ctx.P[0]; \
+ BF_ROUND(L, R, 0); \
+ BF_ROUND(R, L, 1); \
+ BF_ROUND(L, R, 2); \
+ BF_ROUND(R, L, 3); \
+ BF_ROUND(L, R, 4); \
+ BF_ROUND(R, L, 5); \
+ BF_ROUND(L, R, 6); \
+ BF_ROUND(R, L, 7); \
+ BF_ROUND(L, R, 8); \
+ BF_ROUND(R, L, 9); \
+ BF_ROUND(L, R, 10); \
+ BF_ROUND(R, L, 11); \
+ BF_ROUND(L, R, 12); \
+ BF_ROUND(R, L, 13); \
+ BF_ROUND(L, R, 14); \
+ BF_ROUND(R, L, 15); \
+ tmp4 = R; \
+ R = L; \
+ L = tmp4 ^ data.ctx.P[BF_N + 1];
+
+#if BF_ASM
+#define BF_body() \
+ _BF_body_r(&data.ctx);
+#else
+#define BF_body() \
+ L = R = 0; \
+ ptr = data.ctx.P; \
+ do { \
+ ptr += 2; \
+ BF_ENCRYPT; \
+ *(ptr - 2) = L; \
+ *(ptr - 1) = R; \
+ } while (ptr < &data.ctx.P[BF_N + 2]); \
+\
+ ptr = data.ctx.S[0]; \
+ do { \
+ ptr += 2; \
+ BF_ENCRYPT; \
+ *(ptr - 2) = L; \
+ *(ptr - 1) = R; \
+ } while (ptr < &data.ctx.S[3][0xFF]);
+#endif
+
+static void BF_set_key(const char *key, BF_key expanded, BF_key initial,
+ unsigned char flags)
+{
+ const char *ptr = key;
+ unsigned int bug, i, j;
+ BF_word safety, sign, diff, tmp[2];
+
+/*
+ * There was a sign extension bug in older revisions of this function. While
+ * we would have liked to simply fix the bug and move on, we have to provide
+ * a backwards compatibility feature (essentially the bug) for some systems and
+ * a safety measure for some others. The latter is needed because for certain
+ * multiple inputs to the buggy algorithm there exist easily found inputs to
+ * the correct algorithm that produce the same hash. Thus, we optionally
+ * deviate from the correct algorithm just enough to avoid such collisions.
+ * While the bug itself affected the majority of passwords containing
+ * characters with the 8th bit set (although only a percentage of those in a
+ * collision-producing way), the anti-collision safety measure affects
+ * only a subset of passwords containing the '\xff' character (not even all of
+ * those passwords, just some of them). This character is not found in valid
+ * UTF-8 sequences and is rarely used in popular 8-bit character encodings.
+ * Thus, the safety measure is unlikely to cause much annoyance, and is a
+ * reasonable tradeoff to use when authenticating against existing hashes that
+ * are not reliably known to have been computed with the correct algorithm.
+ *
+ * We use an approach that tries to minimize side-channel leaks of password
+ * information - that is, we mostly use fixed-cost bitwise operations instead
+ * of branches or table lookups. (One conditional branch based on password
+ * length remains. It is not part of the bug aftermath, though, and is
+ * difficult and possibly unreasonable to avoid given the use of C strings by
+ * the caller, which results in similar timing leaks anyway.)
+ *
+ * For actual implementation, we set an array index in the variable "bug"
+ * (0 means no bug, 1 means sign extension bug emulation) and a flag in the
+ * variable "safety" (bit 16 is set when the safety measure is requested).
+ * Valid combinations of settings are:
+ *
+ * Prefix "$2a$": bug = 0, safety = 0x10000
+ * Prefix "$2x$": bug = 1, safety = 0
+ * Prefix "$2y$": bug = 0, safety = 0
+ */
+ bug = (unsigned int)flags & 1;
+ safety = ((BF_word)flags & 2) << 15;
+
+ sign = diff = 0;
+
+ for (i = 0; i < BF_N + 2; i++) {
+ tmp[0] = tmp[1] = 0;
+ for (j = 0; j < 4; j++) {
+ tmp[0] <<= 8;
+ tmp[0] |= (unsigned char)*ptr; /* correct */
+ tmp[1] <<= 8;
+ tmp[1] |= (BF_word_signed)(signed char)*ptr; /* bug */
+/*
+ * Sign extension in the first char has no effect - nothing to overwrite yet,
+ * and those extra 24 bits will be fully shifted out of the 32-bit word. For
+ * chars 2, 3, 4 in each four-char block, we set bit 7 of "sign" if sign
+ * extension in tmp[1] occurs. Once this flag is set, it remains set.
+ */
+ if (j)
+ sign |= tmp[1] & 0x80;
+ if (!*ptr)
+ ptr = key;
+ else
+ ptr++;
+ }
+ diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */
+
+ expanded[i] = tmp[bug];
+ initial[i] = BF_init_state.P[i] ^ tmp[bug];
+ }
+
+/*
+ * At this point, "diff" is zero iff the correct and buggy algorithms produced
+ * exactly the same result. If so and if "sign" is non-zero, which indicates
+ * that there was a non-benign sign extension, this means that we have a
+ * collision between the correctly computed hash for this password and a set of
+ * passwords that could be supplied to the buggy algorithm. Our safety measure
+ * is meant to protect from such many-buggy to one-correct collisions, by
+ * deviating from the correct algorithm in such cases. Let's check for this.
+ */
+ diff |= diff >> 16; /* still zero iff exact match */
+ diff &= 0xffff; /* ditto */
+ diff += 0xffff; /* bit 16 set iff "diff" was non-zero (on non-match) */
+ sign <<= 9; /* move the non-benign sign extension flag to bit 16 */
+ sign &= ~diff & safety; /* action needed? */
+
+/*
+ * If we have determined that we need to deviate from the correct algorithm,
+ * flip bit 16 in initial expanded key. (The choice of 16 is arbitrary, but
+ * let's stick to it now. It came out of the approach we used above, and it's
+ * not any worse than any other choice we could make.)
+ *
+ * It is crucial that we don't do the same to the expanded key used in the main
+ * Eksblowfish loop. By doing it to only one of these two, we deviate from a
+ * state that could be directly specified by a password to the buggy algorithm
+ * (and to the fully correct one as well, but that's a side-effect).
+ */
+ initial[0] ^= sign;
+}
+
+static char *BF_crypt(const char *key, const char *setting,
+ char *output, int size,
+ BF_word min)
+{
+#if BF_ASM
+ extern void _BF_body_r(BF_ctx *ctx);
+#endif
+ static const unsigned char flags_by_subtype[26] =
+ {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0};
+ struct {
+ BF_ctx ctx;
+ BF_key expanded_key;
+ union {
+ BF_word salt[4];
+ BF_word output[6];
+ } binary;
+ } data;
+ BF_word L, R;
+ BF_word tmp1, tmp2, tmp3, tmp4;
+ BF_word *ptr;
+ BF_word count;
+ int i;
+
+ if (size < 7 + 22 + 31 + 1) {
+ __set_errno(ERANGE);
+ return NULL;
+ }
+
+ if (setting[0] != '$' ||
+ setting[1] != '2' ||
+ setting[2] < 'a' || setting[2] > 'z' ||
+ !flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a'] ||
+ setting[3] != '$' ||
+ setting[4] < '0' || setting[4] > '1' ||
+ setting[5] < '0' || setting[5] > '9' ||
+ (setting[4] == '1' && setting[5] > '7') ||
+ setting[6] != '$') {
+ __set_errno(EINVAL);
+ return NULL;
+ }
+
+ count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
+ if (count < min || BF_decode(data.binary.salt, &setting[7], 16)) {
+ __set_errno(EINVAL);
+ return NULL;
+ }
+ BF_swap(data.binary.salt, 4);
+
+ BF_set_key(key, data.expanded_key, data.ctx.P,
+ flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a']);
+
+ memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));
+
+ L = R = 0;
+ for (i = 0; i < BF_N + 2; i += 2) {
+ L ^= data.binary.salt[i & 2];
+ R ^= data.binary.salt[(i & 2) + 1];
+ BF_ENCRYPT;
+ data.ctx.P[i] = L;
+ data.ctx.P[i + 1] = R;
+ }
+
+ ptr = data.ctx.S[0];
+ do {
+ ptr += 4;
+ L ^= data.binary.salt[(BF_N + 2) & 3];
+ R ^= data.binary.salt[(BF_N + 3) & 3];
+ BF_ENCRYPT;
+ *(ptr - 4) = L;
+ *(ptr - 3) = R;
+
+ L ^= data.binary.salt[(BF_N + 4) & 3];
+ R ^= data.binary.salt[(BF_N + 5) & 3];
+ BF_ENCRYPT;
+ *(ptr - 2) = L;
+ *(ptr - 1) = R;
+ } while (ptr < &data.ctx.S[3][0xFF]);
+
+ do {
+ int done;
+
+ for (i = 0; i < BF_N + 2; i += 2) {
+ data.ctx.P[i] ^= data.expanded_key[i];
+ data.ctx.P[i + 1] ^= data.expanded_key[i + 1];
+ }
+
+ done = 0;
+ do {
+ BF_body();
+ if (done)
+ break;
+ done = 1;
+
+ tmp1 = data.binary.salt[0];
+ tmp2 = data.binary.salt[1];
+ tmp3 = data.binary.salt[2];
+ tmp4 = data.binary.salt[3];
+ for (i = 0; i < BF_N; i += 4) {
+ data.ctx.P[i] ^= tmp1;
+ data.ctx.P[i + 1] ^= tmp2;
+ data.ctx.P[i + 2] ^= tmp3;
+ data.ctx.P[i + 3] ^= tmp4;
+ }
+ data.ctx.P[16] ^= tmp1;
+ data.ctx.P[17] ^= tmp2;
+ } while (1);
+ } while (--count);
+
+ for (i = 0; i < 6; i += 2) {
+ L = BF_magic_w[i];
+ R = BF_magic_w[i + 1];
+
+ count = 64;
+ do {
+ BF_ENCRYPT;
+ } while (--count);
+
+ data.binary.output[i] = L;
+ data.binary.output[i + 1] = R;
+ }
+
+ memcpy(output, setting, 7 + 22 - 1);
+ output[7 + 22 - 1] = BF_itoa64[(int)
+ BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30];
+
+/* This has to be bug-compatible with the original implementation, so
+ * only encode 23 of the 24 bytes. :-) */
+ BF_swap(data.binary.output, 6);
+ BF_encode(&output[7 + 22], data.binary.output, 23);
+ output[7 + 22 + 31] = '\0';
+
+ return output;
+}
+
+int _crypt_output_magic(const char *setting, char *output, int size)
+{
+ if (size < 3)
+ return -1;
+
+ output[0] = '*';
+ output[1] = '0';
+ output[2] = '\0';
+
+ if (setting[0] == '*' && setting[1] == '0')
+ output[1] = '1';
+
+ return 0;
+}
+
+/*
+ * Please preserve the runtime self-test. It serves two purposes at once:
+ *
+ * 1. We really can't afford the risk of producing incompatible hashes e.g.
+ * when there's something like gcc bug 26587 again, whereas an application or
+ * library integrating this code might not also integrate our external tests or
+ * it might not run them after every build. Even if it does, the miscompile
+ * might only occur on the production build, but not on a testing build (such
+ * as because of different optimization settings). It is painful to recover
+ * from incorrectly-computed hashes - merely fixing whatever broke is not
+ * enough. Thus, a proactive measure like this self-test is needed.
+ *
+ * 2. We don't want to leave sensitive data from our actual password hash
+ * computation on the stack or in registers. Previous revisions of the code
+ * would do explicit cleanups, but simply running the self-test after hash
+ * computation is more reliable.
+ *
+ * The performance cost of this quick self-test is around 0.6% at the "$2a$08"
+ * setting.
+ */
+char *_crypt_blowfish_rn(const char *key, const char *setting,
+ char *output, int size)
+{
+ const char *test_key = "8b \xd0\xc1\xd2\xcf\xcc\xd8";
+ const char *test_setting = "$2a$00$abcdefghijklmnopqrstuu";
+ static const char * const test_hash[2] =
+ {"VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55", /* $2x$ */
+ "i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55"}; /* $2a$, $2y$ */
+ char *retval;
+ const char *p;
+ int save_errno, ok;
+ struct {
+ char s[7 + 22 + 1];
+ char o[7 + 22 + 31 + 1 + 1 + 1];
+ } buf;
+
+/* Hash the supplied password */
+ _crypt_output_magic(setting, output, size);
+ retval = BF_crypt(key, setting, output, size, 16);
+ save_errno = errno;
+
+/*
+ * Do a quick self-test. It is important that we make both calls to BF_crypt()
+ * from the same scope such that they likely use the same stack locations,
+ * which makes the second call overwrite the first call's sensitive data on the
+ * stack and makes it more likely that any alignment related issues would be
+ * detected by the self-test.
+ */
+ memcpy(buf.s, test_setting, sizeof(buf.s));
+ if (retval)
+ buf.s[2] = setting[2];
+ memset(buf.o, 0x55, sizeof(buf.o));
+ buf.o[sizeof(buf.o) - 1] = 0;
+ p = BF_crypt(test_key, buf.s, buf.o, sizeof(buf.o) - (1 + 1), 1);
+
+ ok = (p == buf.o &&
+ !memcmp(p, buf.s, 7 + 22) &&
+ !memcmp(p + (7 + 22),
+ test_hash[(unsigned int)(unsigned char)buf.s[2] & 1],
+ 31 + 1 + 1 + 1));
+
+ {
+ const char *k = "\xff\xa3" "34" "\xff\xff\xff\xa3" "345";
+ BF_key ae, ai, ye, yi;
+ BF_set_key(k, ae, ai, 2); /* $2a$ */
+ BF_set_key(k, ye, yi, 4); /* $2y$ */
+ ai[0] ^= 0x10000; /* undo the safety (for comparison) */
+ ok = ok && ai[0] == 0xdb9c59bc && ye[17] == 0x33343500 &&
+ !memcmp(ae, ye, sizeof(ae)) &&
+ !memcmp(ai, yi, sizeof(ai));
+ }
+
+ __set_errno(save_errno);
+ if (ok)
+ return retval;
+
+/* Should not happen */
+ _crypt_output_magic(setting, output, size);
+ __set_errno(EINVAL); /* pretend we don't support this hash type */
+ return NULL;
+}
+
+char *_crypt_gensalt_blowfish_rn(const char *prefix, unsigned long count,
+ const char *input, int size, char *output, int output_size)
+{
+ if (size < 16 || output_size < 7 + 22 + 1 ||
+ (count && (count < 4 || count > 17)) ||
+ prefix[0] != '$' || prefix[1] != '2' ||
+ (prefix[2] != 'a' && prefix[2] != 'y')) {
+ if (output_size > 0) output[0] = '\0';
+ __set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL);
+ return NULL;
+ }
+
+ if (!count) count = 5;
+
+ output[0] = '$';
+ output[1] = '2';
+ output[2] = prefix[2];
+ output[3] = '$';
+ output[4] = '0' + count / 10;
+ output[5] = '0' + count % 10;
+ output[6] = '$';
+
+ BF_encode(&output[7], (const BF_word *)input, 16);
+ output[7 + 22] = '\0';
+
+ return output;
+}
diff --git a/crypto/crypt_blowfish.h b/crypto/crypt_blowfish.h
new file mode 100644
index 0000000..2ee0d8c
--- /dev/null
+++ b/crypto/crypt_blowfish.h
@@ -0,0 +1,27 @@
+/*
+ * Written by Solar Designer <solar at openwall.com> in 2000-2011.
+ * No copyright is claimed, and the software is hereby placed in the public
+ * domain. In case this attempt to disclaim copyright and place the software
+ * in the public domain is deemed null and void, then the software is
+ * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See crypt_blowfish.c for more information.
+ */
+
+#ifndef _CRYPT_BLOWFISH_H
+#define _CRYPT_BLOWFISH_H
+
+extern int _crypt_output_magic(const char *setting, char *output, int size);
+extern char *_crypt_blowfish_rn(const char *key, const char *setting,
+ char *output, int size);
+extern char *_crypt_gensalt_blowfish_rn(const char *prefix,
+ unsigned long count,
+ const char *input, int size, char *output, int output_size);
+
+#endif
diff --git a/crypto/getuuid.c b/crypto/getuuid.c
new file mode 100644
index 0000000..d973c0f
--- /dev/null
+++ b/crypto/getuuid.c
@@ -0,0 +1,208 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This attempts to generate V1 UUIDs according to the Internet Draft
+ * located at http://www.webdav.org/specs/draft-leach-uuids-guids-01.txt
+ */
+#include "apr.h"
+#include "apr_uuid.h"
+#include "apr_md5.h"
+#include "apr_general.h"
+#include "apr_portable.h"
+
+
+#if APR_HAVE_UNISTD_H
+#include <unistd.h> /* for getpid, gethostname */
+#endif
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h> /* for rand, srand */
+#endif
+
+
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#if APR_HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if APR_HAVE_SYS_TIME_H
+#include <sys/time.h> /* for gettimeofday */
+#endif
+
+#define NODE_LENGTH 6
+
+static int uuid_state_seqnum;
+static unsigned char uuid_state_node[NODE_LENGTH] = { 0 };
+
+
+static void get_random_info(unsigned char node[NODE_LENGTH])
+{
+#if APR_HAS_RANDOM
+
+ (void) apr_generate_random_bytes(node, NODE_LENGTH);
+
+#else
+
+ unsigned char seed[APR_MD5_DIGESTSIZE];
+ apr_md5_ctx_t c;
+
+ /* ### probably should revise some of this to be a bit more portable */
+
+ /* Leach & Salz use Linux-specific struct sysinfo;
+ * replace with pid/tid for portability (in the spirit of mod_unique_id) */
+ struct {
+ /* Add thread id here, if applicable, when we get to pthread or apr */
+ pid_t pid;
+#ifdef NETWARE
+ apr_uint64_t t;
+#else
+ struct timeval t;
+#endif
+ char hostname[257];
+
+ } r;
+
+ apr_md5_init(&c);
+#ifdef NETWARE
+ r.pid = NXThreadGetId();
+ NXGetTime(NX_SINCE_BOOT, NX_USECONDS, &(r.t));
+#else
+ r.pid = getpid();
+ gettimeofday(&r.t, (struct timezone *)0);
+#endif
+ gethostname(r.hostname, 256);
+ apr_md5_update(&c, (const unsigned char *)&r, sizeof(r));
+ apr_md5_final(seed, &c);
+
+ memcpy(node, seed, NODE_LENGTH); /* use a subset of the seed bytes */
+#endif
+}
+
+/* This implementation generates a random node ID instead of a
+ system-dependent call to get IEEE node ID. This is also more secure:
+ we aren't passing out our MAC address.
+*/
+static void get_pseudo_node_identifier(unsigned char *node)
+{
+ get_random_info(node);
+ node[0] |= 0x01; /* this designates a random multicast node ID */
+}
+
+static void get_system_time(apr_uint64_t *uuid_time)
+{
+ /* ### fix this call to be more portable? */
+ *uuid_time = apr_time_now();
+
+ /* Offset between UUID formatted times and Unix formatted times.
+ UUID UTC base time is October 15, 1582.
+ Unix base time is January 1, 1970. */
+ *uuid_time = (*uuid_time * 10) + APR_TIME_C(0x01B21DD213814000);
+}
+
+/* true_random -- generate a crypto-quality random number. */
+static int true_random(void)
+{
+ apr_uint64_t time_now;
+
+#if APR_HAS_RANDOM
+ unsigned char buf[2];
+
+ if (apr_generate_random_bytes(buf, 2) == APR_SUCCESS) {
+ return (buf[0] << 8) | buf[1];
+ }
+#endif
+
+ /* crap. this isn't crypto quality, but it will be Good Enough */
+
+ time_now = apr_time_now();
+ srand((unsigned int)(((time_now >> 32) ^ time_now) & 0xffffffff));
+
+ return rand() & 0x0FFFF;
+}
+
+static void init_state(void)
+{
+ uuid_state_seqnum = true_random();
+ get_pseudo_node_identifier(uuid_state_node);
+}
+
+static void get_current_time(apr_uint64_t *timestamp)
+{
+ /* ### this needs to be made thread-safe! */
+
+ apr_uint64_t time_now;
+ static apr_uint64_t time_last = 0;
+ static apr_uint64_t fudge = 0;
+
+ get_system_time(&time_now);
+
+ /* if clock reading changed since last UUID generated... */
+ if (time_last != time_now) {
+ /* The clock reading has changed since the last UUID was generated.
+ Reset the fudge factor. if we are generating them too fast, then
+ the fudge may need to be reset to something greater than zero. */
+ if (time_last + fudge > time_now)
+ fudge = time_last + fudge - time_now + 1;
+ else
+ fudge = 0;
+ time_last = time_now;
+ }
+ else {
+ /* We generated two really fast. Bump the fudge factor. */
+ ++fudge;
+ }
+
+ *timestamp = time_now + fudge;
+}
+
+APU_DECLARE(void) apr_uuid_get(apr_uuid_t *uuid)
+{
+ apr_uint64_t timestamp;
+ unsigned char *d = uuid->data;
+
+#if APR_HAS_OS_UUID
+ if (apr_os_uuid_get(d) == APR_SUCCESS) {
+ return;
+ }
+#endif /* !APR_HAS_OS_UUID */
+
+ if (!uuid_state_node[0])
+ init_state();
+
+ get_current_time(&timestamp);
+
+ /* time_low, uint32 */
+ d[3] = (unsigned char)timestamp;
+ d[2] = (unsigned char)(timestamp >> 8);
+ d[1] = (unsigned char)(timestamp >> 16);
+ d[0] = (unsigned char)(timestamp >> 24);
+ /* time_mid, uint16 */
+ d[5] = (unsigned char)(timestamp >> 32);
+ d[4] = (unsigned char)(timestamp >> 40);
+ /* time_hi_and_version, uint16 */
+ d[7] = (unsigned char)(timestamp >> 48);
+ d[6] = (unsigned char)(((timestamp >> 56) & 0x0F) | 0x10);
+ /* clock_seq_hi_and_reserved, uint8 */
+ d[8] = (unsigned char)(((uuid_state_seqnum >> 8) & 0x3F) | 0x80);
+ /* clock_seq_low, uint8 */
+ d[9] = (unsigned char)uuid_state_seqnum;
+ /* node, byte[6] */
+ memcpy(&d[10], uuid_state_node, NODE_LENGTH);
+}
diff --git a/crypto/uuid.c b/crypto/uuid.c
new file mode 100644
index 0000000..6e45d71
--- /dev/null
+++ b/crypto/uuid.c
@@ -0,0 +1,130 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h> /* for sprintf */
+
+#include "apr.h"
+#include "apr_uuid.h"
+#include "apr_errno.h"
+#include "apr_lib.h"
+
+
+APU_DECLARE(void) apr_uuid_format(char *buffer, const apr_uuid_t *uuid)
+{
+ const unsigned char *d = uuid->data;
+
+ sprintf(buffer,
+ "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
+ d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
+}
+
+/* convert a pair of hex digits to an integer value [0,255] */
+#if 'A' == 65
+static unsigned char parse_hexpair(const char *s)
+{
+ int result;
+ int temp;
+
+ result = s[0] - '0';
+ if (result > 48)
+ result = (result - 39) << 4;
+ else if (result > 16)
+ result = (result - 7) << 4;
+ else
+ result = result << 4;
+
+ temp = s[1] - '0';
+ if (temp > 48)
+ result |= temp - 39;
+ else if (temp > 16)
+ result |= temp - 7;
+ else
+ result |= temp;
+
+ return (unsigned char)result;
+}
+#else
+static unsigned char parse_hexpair(const char *s)
+{
+ int result;
+
+ if (isdigit(*s)) {
+ result = (*s - '0') << 4;
+ }
+ else {
+ if (isupper(*s)) {
+ result = (*s - 'A' + 10) << 4;
+ }
+ else {
+ result = (*s - 'a' + 10) << 4;
+ }
+ }
+
+ ++s;
+ if (isdigit(*s)) {
+ result |= (*s - '0');
+ }
+ else {
+ if (isupper(*s)) {
+ result |= (*s - 'A' + 10);
+ }
+ else {
+ result |= (*s - 'a' + 10);
+ }
+ }
+
+ return (unsigned char)result;
+}
+#endif
+
+APU_DECLARE(apr_status_t) apr_uuid_parse(apr_uuid_t *uuid,
+ const char *uuid_str)
+{
+ int i;
+ unsigned char *d = uuid->data;
+
+ for (i = 0; i < 36; ++i) {
+ char c = uuid_str[i];
+ if (!apr_isxdigit(c) &&
+ !(c == '-' && (i == 8 || i == 13 || i == 18 || i == 23)))
+ /* ### need a better value */
+ return APR_BADARG;
+ }
+ if (uuid_str[36] != '\0') {
+ /* ### need a better value */
+ return APR_BADARG;
+ }
+
+ d[0] = parse_hexpair(&uuid_str[0]);
+ d[1] = parse_hexpair(&uuid_str[2]);
+ d[2] = parse_hexpair(&uuid_str[4]);
+ d[3] = parse_hexpair(&uuid_str[6]);
+
+ d[4] = parse_hexpair(&uuid_str[9]);
+ d[5] = parse_hexpair(&uuid_str[11]);
+
+ d[6] = parse_hexpair(&uuid_str[14]);
+ d[7] = parse_hexpair(&uuid_str[16]);
+
+ d[8] = parse_hexpair(&uuid_str[19]);
+ d[9] = parse_hexpair(&uuid_str[21]);
+
+ for (i = 6; i--;)
+ d[10 + i] = parse_hexpair(&uuid_str[i*2+24]);
+
+ return APR_SUCCESS;
+}