1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more
2251876Speter * contributor license agreements.  See the NOTICE file distributed with
3251876Speter * this work for additional information regarding copyright ownership.
4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0
5251876Speter * (the "License"); you may not use this file except in compliance with
6251876Speter * the License.  You may obtain a copy of the License at
7251876Speter *
8251876Speter *     http://www.apache.org/licenses/LICENSE-2.0
9251876Speter *
10251876Speter * Unless required by applicable law or agreed to in writing, software
11251876Speter * distributed under the License is distributed on an "AS IS" BASIS,
12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13251876Speter * See the License for the specific language governing permissions and
14251876Speter * limitations under the License.
15251876Speter */
16251876Speter
17251876Speter#include <ctype.h>
18251876Speter#include <stdio.h>
19251876Speter
20251876Speter#include "apu_config.h"
21251876Speter#include "apu.h"
22251876Speter#include "apr_pools.h"
23251876Speter#include "apr_dso.h"
24251876Speter#include "apr_strings.h"
25251876Speter#include "apr_hash.h"
26251876Speter#include "apr_thread_mutex.h"
27251876Speter#include "apr_lib.h"
28251876Speter
29251876Speter#if APU_HAVE_CRYPTO
30251876Speter
31251876Speter#include "apu_internal.h"
32251876Speter#include "apr_crypto_internal.h"
33251876Speter#include "apr_crypto.h"
34251876Speter#include "apu_version.h"
35251876Speter
36251876Speterstatic apr_hash_t *drivers = NULL;
37251876Speter
38251876Speter#define ERROR_SIZE 1024
39251876Speter
40251876Speter#define CLEANUP_CAST (apr_status_t (*)(void*))
41251876Speter
42251876Speter#define APR_TYPEDEF_STRUCT(type, incompletion) \
43251876Speterstruct type { \
44251876Speter   incompletion \
45251876Speter   void *unk[]; \
46251876Speter};
47251876Speter
48251876SpeterAPR_TYPEDEF_STRUCT(apr_crypto_t,
49251876Speter    apr_pool_t *pool;
50251876Speter    apr_crypto_driver_t *provider;
51251876Speter)
52251876Speter
53251876SpeterAPR_TYPEDEF_STRUCT(apr_crypto_key_t,
54251876Speter    apr_pool_t *pool;
55251876Speter    apr_crypto_driver_t *provider;
56251876Speter    const apr_crypto_t *f;
57251876Speter)
58251876Speter
59251876SpeterAPR_TYPEDEF_STRUCT(apr_crypto_block_t,
60251876Speter    apr_pool_t *pool;
61251876Speter    apr_crypto_driver_t *provider;
62251876Speter    const apr_crypto_t *f;
63251876Speter)
64251876Speter
65251876Spetertypedef struct apr_crypto_clear_t {
66251876Speter    void *buffer;
67251876Speter    apr_size_t size;
68251876Speter} apr_crypto_clear_t;
69251876Speter
70251876Speter#if !APU_DSO_BUILD
71253734Speter#define DRIVER_LOAD(name,driver_name,pool,params,rv,result) \
72251876Speter    {   \
73253734Speter        extern const apr_crypto_driver_t driver_name; \
74253734Speter        apr_hash_set(drivers,name,APR_HASH_KEY_STRING,&driver_name); \
75253734Speter        if (driver_name.init) {     \
76253734Speter            rv = driver_name.init(pool, params, result); \
77251876Speter        }  \
78253734Speter        *driver = &driver_name; \
79251876Speter    }
80251876Speter#endif
81251876Speter
82251876Speterstatic apr_status_t apr_crypto_term(void *ptr)
83251876Speter{
84251876Speter    /* set drivers to NULL so init can work again */
85251876Speter    drivers = NULL;
86251876Speter
87251876Speter    /* Everything else we need is handled by cleanups registered
88251876Speter     * when we created mutexes and loaded DSOs
89251876Speter     */
90251876Speter    return APR_SUCCESS;
91251876Speter}
92251876Speter
93251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_init(apr_pool_t *pool)
94251876Speter{
95251876Speter    apr_status_t ret = APR_SUCCESS;
96251876Speter    apr_pool_t *parent;
97251876Speter
98251876Speter    if (drivers != NULL) {
99251876Speter        return APR_SUCCESS;
100251876Speter    }
101251876Speter
102251876Speter    /* Top level pool scope, need process-scope lifetime */
103251876Speter    for (parent = pool; parent; parent = apr_pool_parent_get(pool))
104251876Speter        pool = parent;
105251876Speter#if APU_DSO_BUILD
106251876Speter    /* deprecate in 2.0 - permit implicit initialization */
107251876Speter    apu_dso_init(pool);
108251876Speter#endif
109251876Speter    drivers = apr_hash_make(pool);
110251876Speter
111251876Speter    apr_pool_cleanup_register(pool, NULL, apr_crypto_term,
112251876Speter            apr_pool_cleanup_null);
113251876Speter
114251876Speter    return ret;
115251876Speter}
116251876Speter
117251876Speterstatic apr_status_t crypto_clear(void *ptr)
118251876Speter{
119251876Speter    apr_crypto_clear_t *clear = (apr_crypto_clear_t *)ptr;
120251876Speter
121251876Speter    memset(clear->buffer, 0, clear->size);
122251876Speter    clear->buffer = NULL;
123251876Speter    clear->size = 0;
124251876Speter
125251876Speter    return APR_SUCCESS;
126251876Speter}
127251876Speter
128251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_clear(apr_pool_t *pool,
129251876Speter        void *buffer, apr_size_t size)
130251876Speter{
131251876Speter    apr_crypto_clear_t *clear = apr_palloc(pool, sizeof(apr_crypto_clear_t));
132251876Speter
133251876Speter    clear->buffer = buffer;
134251876Speter    clear->size = size;
135251876Speter
136251876Speter    apr_pool_cleanup_register(pool, clear, crypto_clear,
137251876Speter            apr_pool_cleanup_null);
138251876Speter
139251876Speter    return APR_SUCCESS;
140251876Speter}
141251876Speter
142251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_get_driver(
143251876Speter        const apr_crypto_driver_t **driver, const char *name,
144251876Speter        const char *params, const apu_err_t **result, apr_pool_t *pool)
145251876Speter{
146251876Speter#if APU_DSO_BUILD
147251876Speter    char modname[32];
148251876Speter    char symname[34];
149251876Speter    apr_dso_handle_t *dso;
150251876Speter    apr_dso_handle_sym_t symbol;
151251876Speter#endif
152251876Speter    apr_status_t rv;
153251876Speter
154253734Speter    if (result) {
155253734Speter        *result = NULL; /* until further notice */
156253734Speter    }
157253734Speter
158251876Speter#if APU_DSO_BUILD
159251876Speter    rv = apu_dso_mutex_lock();
160251876Speter    if (rv) {
161251876Speter        return rv;
162251876Speter    }
163251876Speter#endif
164251876Speter    *driver = apr_hash_get(drivers, name, APR_HASH_KEY_STRING);
165251876Speter    if (*driver) {
166251876Speter#if APU_DSO_BUILD
167251876Speter        apu_dso_mutex_unlock();
168251876Speter#endif
169251876Speter        return APR_SUCCESS;
170251876Speter    }
171251876Speter
172251876Speter#if APU_DSO_BUILD
173251876Speter    /* The driver DSO must have exactly the same lifetime as the
174251876Speter     * drivers hash table; ignore the passed-in pool */
175251876Speter    pool = apr_hash_pool_get(drivers);
176251876Speter
177251876Speter#if defined(NETWARE)
178251876Speter    apr_snprintf(modname, sizeof(modname), "crypto%s.nlm", name);
179251876Speter#elif defined(WIN32)
180251876Speter    apr_snprintf(modname, sizeof(modname),
181251876Speter            "apr_crypto_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".dll", name);
182251876Speter#else
183251876Speter    apr_snprintf(modname, sizeof(modname),
184251876Speter            "apr_crypto_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".so", name);
185251876Speter#endif
186251876Speter    apr_snprintf(symname, sizeof(symname), "apr_crypto_%s_driver", name);
187251876Speter    rv = apu_dso_load(&dso, &symbol, modname, symname, pool);
188253734Speter    if (rv == APR_SUCCESS || rv == APR_EINIT) { /* previously loaded?!? */
189253734Speter        *driver = symbol;
190253734Speter        name = apr_pstrdup(pool, name);
191253734Speter        apr_hash_set(drivers, name, APR_HASH_KEY_STRING, *driver);
192253734Speter        rv = APR_SUCCESS;
193253734Speter        if ((*driver)->init) {
194253734Speter            rv = (*driver)->init(pool, params, result);
195251876Speter        }
196251876Speter    }
197253734Speter    apu_dso_mutex_unlock();
198251876Speter
199253734Speter    if (APR_SUCCESS != rv && result && !*result) {
200251876Speter        char *buffer = apr_pcalloc(pool, ERROR_SIZE);
201251876Speter        apu_err_t *err = apr_pcalloc(pool, sizeof(apu_err_t));
202251876Speter        if (err && buffer) {
203251876Speter            apr_dso_error(dso, buffer, ERROR_SIZE - 1);
204251876Speter            err->msg = buffer;
205251876Speter            err->reason = modname;
206251876Speter            *result = err;
207251876Speter        }
208251876Speter    }
209251876Speter
210251876Speter#else /* not builtin and !APR_HAS_DSO => not implemented */
211251876Speter    rv = APR_ENOTIMPL;
212253734Speter
213253734Speter    /* Load statically-linked drivers: */
214253734Speter#if APU_HAVE_OPENSSL
215253734Speter    if (name[0] == 'o' && !strcmp(name, "openssl")) {
216253734Speter        DRIVER_LOAD("openssl", apr_crypto_openssl_driver, pool, params, rv, result);
217253734Speter    }
218251876Speter#endif
219253734Speter#if APU_HAVE_NSS
220253734Speter    if (name[0] == 'n' && !strcmp(name, "nss")) {
221253734Speter        DRIVER_LOAD("nss", apr_crypto_nss_driver, pool, params, rv, result);
222253734Speter    }
223253734Speter#endif
224253734Speter#if APU_HAVE_MSCAPI
225253734Speter    if (name[0] == 'm' && !strcmp(name, "mscapi")) {
226253734Speter        DRIVER_LOAD("mscapi", apr_crypto_mscapi_driver, pool, params, rv, result);
227253734Speter    }
228253734Speter#endif
229253734Speter#if APU_HAVE_MSCNG
230253734Speter    if (name[0] == 'm' && !strcmp(name, "mscng")) {
231253734Speter        DRIVER_LOAD("mscng", apr_crypto_mscng_driver, pool, params, rv, result);
232253734Speter    }
233253734Speter#endif
234251876Speter
235253734Speter#endif
236253734Speter
237251876Speter    return rv;
238251876Speter}
239251876Speter
240251876Speter/**
241251876Speter * @brief Return the name of the driver.
242251876Speter *
243251876Speter * @param driver - The driver in use.
244251876Speter * @return The name of the driver.
245251876Speter */
246251876SpeterAPU_DECLARE(const char *)apr_crypto_driver_name (
247251876Speter        const apr_crypto_driver_t *driver)
248251876Speter{
249251876Speter    return driver->name;
250251876Speter}
251251876Speter
252251876Speter/**
253251876Speter * @brief Get the result of the last operation on a context. If the result
254251876Speter *        is NULL, the operation was successful.
255251876Speter * @param result - the result structure
256251876Speter * @param f - context pointer
257251876Speter * @return APR_SUCCESS for success
258251876Speter */
259251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_error(const apu_err_t **result,
260251876Speter        const apr_crypto_t *f)
261251876Speter{
262251876Speter    return f->provider->error(result, f);
263251876Speter}
264251876Speter
265251876Speter/**
266251876Speter * @brief Create a context for supporting encryption. Keys, certificates,
267251876Speter *        algorithms and other parameters will be set per context. More than
268251876Speter *        one context can be created at one time. A cleanup will be automatically
269251876Speter *        registered with the given pool to guarantee a graceful shutdown.
270251876Speter * @param f - context pointer will be written here
271251876Speter * @param driver - driver to use
272251876Speter * @param params - array of key parameters
273251876Speter * @param pool - process pool
274251876Speter * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
275251876Speter * if the engine cannot be initialised.
276251876Speter * @remarks NSS: currently no params are supported.
277251876Speter * @remarks OpenSSL: the params can have "engine" as a key, followed by an equal
278251876Speter *  sign and a value.
279251876Speter */
280251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_make(apr_crypto_t **f,
281251876Speter        const apr_crypto_driver_t *driver, const char *params, apr_pool_t *pool)
282251876Speter{
283251876Speter    return driver->make(f, driver, params, pool);
284251876Speter}
285251876Speter
286251876Speter/**
287251876Speter * @brief Get a hash table of key types, keyed by the name of the type against
288251876Speter * an integer pointer constant.
289251876Speter *
290251876Speter * @param types - hashtable of key types keyed to constants.
291251876Speter * @param f - encryption context
292251876Speter * @return APR_SUCCESS for success
293251876Speter */
294251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_get_block_key_types(apr_hash_t **types,
295251876Speter        const apr_crypto_t *f)
296251876Speter{
297251876Speter    return f->provider->get_block_key_types(types, f);
298251876Speter}
299251876Speter
300251876Speter/**
301251876Speter * @brief Get a hash table of key modes, keyed by the name of the mode against
302251876Speter * an integer pointer constant.
303251876Speter *
304251876Speter * @param modes - hashtable of key modes keyed to constants.
305251876Speter * @param f - encryption context
306251876Speter * @return APR_SUCCESS for success
307251876Speter */
308251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_get_block_key_modes(apr_hash_t **modes,
309251876Speter        const apr_crypto_t *f)
310251876Speter{
311251876Speter    return f->provider->get_block_key_modes(modes, f);
312251876Speter}
313251876Speter
314251876Speter/**
315251876Speter * @brief Create a key from the given passphrase. By default, the PBKDF2
316251876Speter *        algorithm is used to generate the key from the passphrase. It is expected
317251876Speter *        that the same pass phrase will generate the same key, regardless of the
318251876Speter *        backend crypto platform used. The key is cleaned up when the context
319251876Speter *        is cleaned, and may be reused with multiple encryption or decryption
320251876Speter *        operations.
321251876Speter * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
322251876Speter *       *key is not NULL, *key must point at a previously created structure.
323251876Speter * @param key The key returned, see note.
324251876Speter * @param ivSize The size of the initialisation vector will be returned, based
325251876Speter *               on whether an IV is relevant for this type of crypto.
326251876Speter * @param pass The passphrase to use.
327251876Speter * @param passLen The passphrase length in bytes
328251876Speter * @param salt The salt to use.
329251876Speter * @param saltLen The salt length in bytes
330251876Speter * @param type 3DES_192, AES_128, AES_192, AES_256.
331251876Speter * @param mode Electronic Code Book / Cipher Block Chaining.
332251876Speter * @param doPad Pad if necessary.
333251876Speter * @param iterations Number of iterations to use in algorithm
334251876Speter * @param f The context to use.
335251876Speter * @param p The pool to use.
336251876Speter * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
337251876Speter *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
338251876Speter *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
339251876Speter *         not known. APR_EPADDING if padding was requested but is not supported.
340251876Speter *         APR_ENOTIMPL if not implemented.
341251876Speter */
342251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_passphrase(apr_crypto_key_t **key,
343251876Speter        apr_size_t *ivSize, const char *pass, apr_size_t passLen,
344251876Speter        const unsigned char * salt, apr_size_t saltLen,
345251876Speter        const apr_crypto_block_key_type_e type,
346251876Speter        const apr_crypto_block_key_mode_e mode, const int doPad,
347251876Speter        const int iterations, const apr_crypto_t *f, apr_pool_t *p)
348251876Speter{
349251876Speter    return f->provider->passphrase(key, ivSize, pass, passLen, salt, saltLen,
350251876Speter            type, mode, doPad, iterations, f, p);
351251876Speter}
352251876Speter
353251876Speter/**
354251876Speter * @brief Initialise a context for encrypting arbitrary data using the given key.
355251876Speter * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
356251876Speter *       *ctx is not NULL, *ctx must point at a previously created structure.
357251876Speter * @param ctx The block context returned, see note.
358251876Speter * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
359251876Speter *           an IV will be created at random, in space allocated from the pool.
360251876Speter *           If the buffer pointed to is not NULL, the IV in the buffer will be
361251876Speter *           used.
362251876Speter * @param key The key structure to use.
363251876Speter * @param blockSize The block size of the cipher.
364251876Speter * @param p The pool to use.
365251876Speter * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
366251876Speter *         Returns APR_EINIT if the backend failed to initialise the context. Returns
367251876Speter *         APR_ENOTIMPL if not implemented.
368251876Speter */
369251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_block_encrypt_init(
370251876Speter        apr_crypto_block_t **ctx, const unsigned char **iv,
371251876Speter        const apr_crypto_key_t *key, apr_size_t *blockSize, apr_pool_t *p)
372251876Speter{
373251876Speter    return key->provider->block_encrypt_init(ctx, iv, key, blockSize, p);
374251876Speter}
375251876Speter
376251876Speter/**
377251876Speter * @brief Encrypt data provided by in, write it to out.
378251876Speter * @note The number of bytes written will be written to outlen. If
379251876Speter *       out is NULL, outlen will contain the maximum size of the
380251876Speter *       buffer needed to hold the data, including any data
381251876Speter *       generated by apr_crypto_block_encrypt_finish below. If *out points
382251876Speter *       to NULL, a buffer sufficiently large will be created from
383251876Speter *       the pool provided. If *out points to a not-NULL value, this
384251876Speter *       value will be used as a buffer instead.
385251876Speter * @param out Address of a buffer to which data will be written,
386251876Speter *        see note.
387251876Speter * @param outlen Length of the output will be written here.
388251876Speter * @param in Address of the buffer to read.
389251876Speter * @param inlen Length of the buffer to read.
390251876Speter * @param ctx The block context to use.
391251876Speter * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
392251876Speter *         not implemented.
393251876Speter */
394251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_block_encrypt(unsigned char **out,
395251876Speter        apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
396251876Speter        apr_crypto_block_t *ctx)
397251876Speter{
398251876Speter    return ctx->provider->block_encrypt(out, outlen, in, inlen, ctx);
399251876Speter}
400251876Speter
401251876Speter/**
402251876Speter * @brief Encrypt final data block, write it to out.
403251876Speter * @note If necessary the final block will be written out after being
404251876Speter *       padded. Typically the final block will be written to the
405251876Speter *       same buffer used by apr_crypto_block_encrypt, offset by the
406251876Speter *       number of bytes returned as actually written by the
407251876Speter *       apr_crypto_block_encrypt() call. After this call, the context
408251876Speter *       is cleaned and can be reused by apr_crypto_block_encrypt_init().
409251876Speter * @param out Address of a buffer to which data will be written. This
410251876Speter *            buffer must already exist, and is usually the same
411251876Speter *            buffer used by apr_evp_crypt(). See note.
412251876Speter * @param outlen Length of the output will be written here.
413251876Speter * @param ctx The block context to use.
414251876Speter * @return APR_ECRYPT if an error occurred.
415251876Speter * @return APR_EPADDING if padding was enabled and the block was incorrectly
416251876Speter *         formatted.
417251876Speter * @return APR_ENOTIMPL if not implemented.
418251876Speter */
419251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_block_encrypt_finish(unsigned char *out,
420251876Speter        apr_size_t *outlen, apr_crypto_block_t *ctx)
421251876Speter{
422251876Speter    return ctx->provider->block_encrypt_finish(out, outlen, ctx);
423251876Speter}
424251876Speter
425251876Speter/**
426251876Speter * @brief Initialise a context for decrypting arbitrary data using the given key.
427251876Speter * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
428251876Speter *       *ctx is not NULL, *ctx must point at a previously created structure.
429251876Speter * @param ctx The block context returned, see note.
430251876Speter * @param blockSize The block size of the cipher.
431251876Speter * @param iv Optional initialisation vector.
432251876Speter * @param key The key structure to use.
433251876Speter * @param p The pool to use.
434251876Speter * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
435251876Speter *         Returns APR_EINIT if the backend failed to initialise the context. Returns
436251876Speter *         APR_ENOTIMPL if not implemented.
437251876Speter */
438251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_block_decrypt_init(
439251876Speter        apr_crypto_block_t **ctx, apr_size_t *blockSize,
440251876Speter        const unsigned char *iv, const apr_crypto_key_t *key, apr_pool_t *p)
441251876Speter{
442251876Speter    return key->provider->block_decrypt_init(ctx, blockSize, iv, key, p);
443251876Speter}
444251876Speter
445251876Speter/**
446251876Speter * @brief Decrypt data provided by in, write it to out.
447251876Speter * @note The number of bytes written will be written to outlen. If
448251876Speter *       out is NULL, outlen will contain the maximum size of the
449251876Speter *       buffer needed to hold the data, including any data
450251876Speter *       generated by apr_crypto_block_decrypt_finish below. If *out points
451251876Speter *       to NULL, a buffer sufficiently large will be created from
452251876Speter *       the pool provided. If *out points to a not-NULL value, this
453251876Speter *       value will be used as a buffer instead.
454251876Speter * @param out Address of a buffer to which data will be written,
455251876Speter *        see note.
456251876Speter * @param outlen Length of the output will be written here.
457251876Speter * @param in Address of the buffer to read.
458251876Speter * @param inlen Length of the buffer to read.
459251876Speter * @param ctx The block context to use.
460251876Speter * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
461251876Speter *         not implemented.
462251876Speter */
463251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_block_decrypt(unsigned char **out,
464251876Speter        apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
465251876Speter        apr_crypto_block_t *ctx)
466251876Speter{
467251876Speter    return ctx->provider->block_decrypt(out, outlen, in, inlen, ctx);
468251876Speter}
469251876Speter
470251876Speter/**
471251876Speter * @brief Decrypt final data block, write it to out.
472251876Speter * @note If necessary the final block will be written out after being
473251876Speter *       padded. Typically the final block will be written to the
474251876Speter *       same buffer used by apr_crypto_block_decrypt, offset by the
475251876Speter *       number of bytes returned as actually written by the
476251876Speter *       apr_crypto_block_decrypt() call. After this call, the context
477251876Speter *       is cleaned and can be reused by apr_crypto_block_decrypt_init().
478251876Speter * @param out Address of a buffer to which data will be written. This
479251876Speter *            buffer must already exist, and is usually the same
480251876Speter *            buffer used by apr_evp_crypt(). See note.
481251876Speter * @param outlen Length of the output will be written here.
482251876Speter * @param ctx The block context to use.
483251876Speter * @return APR_ECRYPT if an error occurred.
484251876Speter * @return APR_EPADDING if padding was enabled and the block was incorrectly
485251876Speter *         formatted.
486251876Speter * @return APR_ENOTIMPL if not implemented.
487251876Speter */
488251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_block_decrypt_finish(unsigned char *out,
489251876Speter        apr_size_t *outlen, apr_crypto_block_t *ctx)
490251876Speter{
491251876Speter    return ctx->provider->block_decrypt_finish(out, outlen, ctx);
492251876Speter}
493251876Speter
494251876Speter/**
495251876Speter * @brief Clean encryption / decryption context.
496251876Speter * @note After cleanup, a context is free to be reused if necessary.
497251876Speter * @param ctx The block context to use.
498251876Speter * @return Returns APR_ENOTIMPL if not supported.
499251876Speter */
500251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_block_cleanup(apr_crypto_block_t *ctx)
501251876Speter{
502251876Speter    return ctx->provider->block_cleanup(ctx);
503251876Speter}
504251876Speter
505251876Speter/**
506251876Speter * @brief Clean encryption / decryption context.
507251876Speter * @note After cleanup, a context is free to be reused if necessary.
508251876Speter * @param f The context to use.
509251876Speter * @return Returns APR_ENOTIMPL if not supported.
510251876Speter */
511251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_cleanup(apr_crypto_t *f)
512251876Speter{
513251876Speter    return f->provider->cleanup(f);
514251876Speter}
515251876Speter
516251876Speter/**
517251876Speter * @brief Shutdown the crypto library.
518251876Speter * @note After shutdown, it is expected that the init function can be called again.
519251876Speter * @param driver - driver to use
520251876Speter * @return Returns APR_ENOTIMPL if not supported.
521251876Speter */
522251876SpeterAPU_DECLARE(apr_status_t) apr_crypto_shutdown(const apr_crypto_driver_t *driver)
523251876Speter{
524251876Speter    return driver->shutdown();
525251876Speter}
526251876Speter
527251876Speter#endif /* APU_HAVE_CRYPTO */
528