diff options
Diffstat (limited to 'crypto/apr_crypto_openssl.c')
-rw-r--r-- | crypto/apr_crypto_openssl.c | 372 |
1 files changed, 260 insertions, 112 deletions
diff --git a/crypto/apr_crypto_openssl.c b/crypto/apr_crypto_openssl.c index a9dda907..97e6008e 100644 --- a/crypto/apr_crypto_openssl.c +++ b/crypto/apr_crypto_openssl.c @@ -14,9 +14,8 @@ * limitations under the License. */ +#include "apr_lib.h" #include "apu.h" - -#include "apu_config.h" #include "apu_errno.h" #include <ctype.h> @@ -36,11 +35,24 @@ #define LOG_PREFIX "apr_crypto_openssl: " +struct apr_crypto_t { + apr_pool_t *pool; + const apr_crypto_driver_t *provider; + apu_err_t *result; + apr_array_header_t *keys; + 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; @@ -49,8 +61,9 @@ struct apr_crypto_key_t { }; struct apr_crypto_block_t { - const apr_crypto_t *factory; apr_pool_t *pool; + const apr_crypto_driver_t *provider; + const apr_crypto_t *f; EVP_CIPHER_CTX cipherCtx; int initialised; int ivSize; @@ -58,26 +71,45 @@ struct apr_crypto_block_t { int doPad; }; +static int key_3des_192 = APR_KEY_3DES_192; +static int key_aes_128 = APR_KEY_AES_128; +static int key_aes_192 = APR_KEY_AES_192; +static int key_aes_256 = APR_KEY_AES_256; + +static int mode_ecb = APR_MODE_ECB; +static int mode_cbc = 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(apr_pool_t *pool) { +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) { - apr_pool_t *pool = (apr_pool_t *) data; - return crypto_shutdown(pool); +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 apr_array_header_t *params, int *rc) { +static apr_status_t crypto_init(apr_pool_t *pool, const char *params, int *rc) +{ CRYPTO_malloc_init(); ERR_load_crypto_strings(); /* SSL_load_error_strings(); */ @@ -94,11 +126,11 @@ static apr_status_t crypto_init(apr_pool_t *pool, /** * @brief Clean encryption / decryption context. * @note After cleanup, a context is free to be reused if necessary. - * @param driver - driver to use * @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) { +static apr_status_t crypto_block_cleanup(apr_crypto_block_t *ctx) +{ if (ctx->initialised) { EVP_CIPHER_CTX_cleanup(&ctx->cipherCtx); @@ -109,19 +141,20 @@ static apr_status_t crypto_block_cleanup(apr_crypto_block_t *ctx) { } -static apr_status_t crypto_block_cleanup_helper(void *data) { +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 factory. - * @note After cleanup, a factory is free to be reused if necessary. - * @param driver - driver to use - * @param f The factory to use. + * @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) { +static apr_status_t crypto_cleanup(apr_crypto_t *f) +{ if (f->config->engine) { ENGINE_finish(f->config->engine); @@ -132,7 +165,8 @@ static apr_status_t crypto_cleanup(apr_crypto_t *f) { } -static apr_status_t crypto_cleanup_helper(void *data) { +static apr_status_t crypto_cleanup_helper(void *data) +{ apr_crypto_t *f = (apr_crypto_t *) data; return crypto_cleanup(f); } @@ -142,51 +176,118 @@ static apr_status_t crypto_cleanup_helper(void *data) { * 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 driver - driver to use - * @param pool - process pool + * @param f - context pointer will be written here + * @param provider - provider to use * @param params - array of key parameters - * @param factory - factory pointer will be written here + * @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_factory(apr_pool_t *pool, - const apr_array_header_t *params, apr_crypto_t **factory) { +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; - struct apr_crypto_param_t *ents = - params ? (struct apr_crypto_param_t *) params->elts : NULL; - int i = 0; 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; } - *factory = f; + *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->keys = apr_array_make(pool, 10, sizeof(apr_crypto_key_t)); + if (!f->keys) { + 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_3des_192)); + apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_aes_128)); + apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_aes_192)); + apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_aes_256)); + + f->modes = apr_hash_make(pool); + if (!f->modes) { + return APR_ENOMEM; + } + apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(mode_ecb)); + apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(mode_cbc)); apr_pool_cleanup_register(pool, f, crypto_cleanup_helper, apr_pool_cleanup_null); - for (i = 0; params && i < params->nelts; i++) { - switch (ents[i].type) { - case APR_CRYPTO_ENGINE: - config->engine = ENGINE_by_id(ents[i].path); - if (!config->engine) { - return APR_ENOENGINE; - } - if (!ENGINE_init(config->engine)) { - ENGINE_free(config->engine); - config->engine = NULL; - return APR_EINITENGINE; - } - break; + 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; } } @@ -195,6 +296,36 @@ static apr_status_t crypto_factory(apr_pool_t *pool, } /** + * @brief Get a hash table of key types, keyed by the name of the type against + * an integer pointer constant. + * + * @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 + * an integer pointer constant. + * + * @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; +} + +/** * @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 @@ -203,9 +334,9 @@ static apr_status_t crypto_factory(apr_pool_t *pool, * 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 driver - driver to use - * @param p The pool to use. - * @param f The context to use. + * @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. @@ -213,20 +344,21 @@ static apr_status_t crypto_factory(apr_pool_t *pool, * @param type 3DES_192, AES_128, AES_192, AES_256. * @param mode Electronic Code Book / Cipher Block Chaining. * @param doPad Pad if necessary. - * @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 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_pool_t *p, const apr_crypto_t *f, +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, apr_crypto_key_t **k, apr_size_t *ivSize) { + const int iterations, const apr_crypto_t *f, apr_pool_t *p) +{ apr_crypto_key_t *key = *k; if (!key) { @@ -236,42 +368,49 @@ static apr_status_t crypto_passphrase(apr_pool_t *p, const apr_crypto_t *f, return APR_ENOMEM; } + key->f = f; + key->provider = f->provider; + /* determine the cipher to be used */ switch (type) { - case (KEY_3DES_192): + case (APR_KEY_3DES_192): /* A 3DES key */ - if (mode == MODE_CBC) { + if (mode == APR_MODE_CBC) { key->cipher = EVP_des_ede3_cbc(); - } else { + } + else { key->cipher = EVP_des_ede3_ecb(); } break; - case (KEY_AES_128): + case (APR_KEY_AES_128): - if (mode == MODE_CBC) { + if (mode == APR_MODE_CBC) { key->cipher = EVP_aes_128_cbc(); - } else { + } + else { key->cipher = EVP_aes_128_ecb(); } break; - case (KEY_AES_192): + case (APR_KEY_AES_192): - if (mode == MODE_CBC) { + if (mode == APR_MODE_CBC) { key->cipher = EVP_aes_192_cbc(); - } else { + } + else { key->cipher = EVP_aes_192_ecb(); } break; - case (KEY_AES_256): + case (APR_KEY_AES_256): - if (mode == MODE_CBC) { + if (mode == APR_MODE_CBC) { key->cipher = EVP_aes_256_cbc(); - } else { + } + else { key->cipher = EVP_aes_256_ecb(); } break; @@ -291,6 +430,7 @@ static apr_status_t crypto_passphrase(apr_pool_t *p, const apr_crypto_t *f, if (!key->key) { return APR_ENOMEM; } + apr_crypto_clear(p, key->key, key->keyLen); /* generate the key */ if (PKCS5_PBKDF2_HMAC_SHA1(pass, passLen, (unsigned char *) salt, saltLen, @@ -303,7 +443,7 @@ static apr_status_t crypto_passphrase(apr_pool_t *p, const apr_crypto_t *f, /* note: openssl incorrectly returns non zero IV size values for ECB * algorithms, so work around this by ignoring the IV size. */ - if (MODE_ECB != mode) { + if (APR_MODE_ECB != mode) { key->ivSize = EVP_CIPHER_iv_length(key->cipher); } if (ivSize) { @@ -317,26 +457,24 @@ static apr_status_t crypto_passphrase(apr_pool_t *p, const apr_crypto_t *f, * @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 p The pool to use. - * @param f The block factory to use. - * @param type 3DES_192, AES_128, AES_192, AES_256. - * @param mode Electronic Code Book / Cipher Block Chaining. - * @param key The key - * @param keyLen The key length in bytes - * @param iv Optional initialisation vector. - * @param doPad Pad if necessary. * @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_pool_t *p, - const apr_crypto_t *f, const apr_crypto_key_t *key, - const unsigned char **iv, apr_crypto_block_t **ctx, - apr_size_t *blockSize) { +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 = f->config; + 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)); @@ -344,8 +482,9 @@ static apr_status_t crypto_block_encrypt_init(apr_pool_t *p, if (!block) { return APR_ENOMEM; } - block->factory = f; + 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); @@ -365,12 +504,14 @@ static apr_status_t crypto_block_encrypt_init(apr_pool_t *p, 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 { + } + else { usedIv = (unsigned char *) *iv; } } @@ -407,18 +548,19 @@ static apr_status_t crypto_block_encrypt_init(apr_pool_t *p, * 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 ctx The block context to use. * @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(apr_crypto_block_t *ctx, - unsigned char **out, apr_size_t *outlen, const unsigned char *in, - apr_size_t inlen) { +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; @@ -434,6 +576,7 @@ static apr_status_t crypto_block_encrypt(apr_crypto_block_t *ctx, if (!buffer) { return APR_ENOMEM; } + apr_crypto_clear(ctx->pool, buffer, inlen + EVP_MAX_BLOCK_LENGTH); *out = buffer; } @@ -459,18 +602,19 @@ static apr_status_t crypto_block_encrypt(apr_crypto_block_t *ctx, * 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 ctx The block context to use. * @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(apr_crypto_block_t *ctx, - unsigned char *out, apr_size_t *outlen) { +static apr_status_t crypto_block_encrypt_finish(unsigned char *out, + apr_size_t *outlen, apr_crypto_block_t *ctx) +{ int len = *outlen; if (EVP_EncryptFinal_ex(&ctx->cipherCtx, out, &len) == 0) { @@ -486,23 +630,22 @@ static apr_status_t crypto_block_encrypt_finish(apr_crypto_block_t *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 p The pool to use. - * @param f The block factory to use. - * @param key The key 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 ctx The block context returned, see note. - * @param blockSize The block size of the cipher. + * @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_pool_t *p, - const apr_crypto_t *f, const apr_crypto_key_t *key, - const unsigned char *iv, apr_crypto_block_t **ctx, - apr_size_t *blockSize) { - apr_crypto_config_t *config = f->config; +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)); @@ -510,8 +653,9 @@ static apr_status_t crypto_block_decrypt_init(apr_pool_t *p, if (!block) { return APR_ENOMEM; } - block->factory = f; + 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); @@ -555,23 +699,23 @@ static apr_status_t crypto_block_decrypt_init(apr_pool_t *p, * @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_final below. If *out points + * 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 ctx The block context to use. * @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(apr_crypto_block_t *ctx, - unsigned char **out, apr_size_t *outlen, const unsigned char *in, - apr_size_t inlen) { - +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; @@ -587,6 +731,7 @@ static apr_status_t crypto_block_decrypt(apr_crypto_block_t *ctx, if (!buffer) { return APR_ENOMEM; } + apr_crypto_clear(ctx->pool, buffer, inlen + EVP_MAX_BLOCK_LENGTH); *out = buffer; } @@ -608,22 +753,23 @@ static apr_status_t crypto_block_decrypt(apr_crypto_block_t *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_evp_crypt, offset by the number of - * bytes returned as actually written by the apr_evp_crypt() - * call. After this call, the context is cleaned and can be - * reused by apr_env_encrypt_init() or apr_env_decrypt_init(). - * @param ctx The block context to use. + * 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(apr_crypto_block_t *ctx, - unsigned char *out, apr_size_t *outlen) { +static apr_status_t crypto_block_decrypt_finish(unsigned char *out, + apr_size_t *outlen, apr_crypto_block_t *ctx) +{ int len = *outlen; @@ -640,10 +786,12 @@ static apr_status_t crypto_block_decrypt_finish(apr_crypto_block_t *ctx, * OpenSSL module. */ APU_MODULE_DECLARE_DATA const apr_crypto_driver_t apr_crypto_openssl_driver = { - "openssl", crypto_init, crypto_factory, 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 }; + "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 +}; #endif |