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 "apr_lib.h"
18251876Speter#include "apu.h"
19251876Speter#include "apu_errno.h"
20251876Speter
21251876Speter#include <ctype.h>
22251876Speter#include <assert.h>
23251876Speter#include <stdlib.h>
24251876Speter
25251876Speter#include "apr_strings.h"
26251876Speter#include "apr_time.h"
27251876Speter#include "apr_buckets.h"
28251876Speter
29251876Speter#include "apr_crypto_internal.h"
30251876Speter
31251876Speter#if APU_HAVE_CRYPTO
32251876Speter
33251876Speter#include <openssl/evp.h>
34251876Speter#include <openssl/engine.h>
35251876Speter
36251876Speter#define LOG_PREFIX "apr_crypto_openssl: "
37251876Speter
38251876Speterstruct apr_crypto_t {
39251876Speter    apr_pool_t *pool;
40251876Speter    const apr_crypto_driver_t *provider;
41251876Speter    apu_err_t *result;
42251876Speter    apr_array_header_t *keys;
43251876Speter    apr_crypto_config_t *config;
44251876Speter    apr_hash_t *types;
45251876Speter    apr_hash_t *modes;
46251876Speter};
47251876Speter
48251876Speterstruct apr_crypto_config_t {
49251876Speter    ENGINE *engine;
50251876Speter};
51251876Speter
52251876Speterstruct apr_crypto_key_t {
53251876Speter    apr_pool_t *pool;
54251876Speter    const apr_crypto_driver_t *provider;
55251876Speter    const apr_crypto_t *f;
56251876Speter    const EVP_CIPHER * cipher;
57251876Speter    unsigned char *key;
58251876Speter    int keyLen;
59251876Speter    int doPad;
60251876Speter    int ivSize;
61251876Speter};
62251876Speter
63251876Speterstruct apr_crypto_block_t {
64251876Speter    apr_pool_t *pool;
65251876Speter    const apr_crypto_driver_t *provider;
66251876Speter    const apr_crypto_t *f;
67251876Speter    EVP_CIPHER_CTX cipherCtx;
68251876Speter    int initialised;
69251876Speter    int ivSize;
70251876Speter    int blockSize;
71251876Speter    int doPad;
72251876Speter};
73251876Speter
74251876Speterstatic int key_3des_192 = APR_KEY_3DES_192;
75251876Speterstatic int key_aes_128 = APR_KEY_AES_128;
76251876Speterstatic int key_aes_192 = APR_KEY_AES_192;
77251876Speterstatic int key_aes_256 = APR_KEY_AES_256;
78251876Speter
79251876Speterstatic int mode_ecb = APR_MODE_ECB;
80251876Speterstatic int mode_cbc = APR_MODE_CBC;
81251876Speter
82251876Speter/**
83251876Speter * Fetch the most recent error from this driver.
84251876Speter */
85251876Speterstatic apr_status_t crypto_error(const apu_err_t **result,
86251876Speter        const apr_crypto_t *f)
87251876Speter{
88251876Speter    *result = f->result;
89251876Speter    return APR_SUCCESS;
90251876Speter}
91251876Speter
92251876Speter/**
93251876Speter * Shutdown the crypto library and release resources.
94251876Speter */
95251876Speterstatic apr_status_t crypto_shutdown(void)
96251876Speter{
97251876Speter    ERR_free_strings();
98251876Speter    EVP_cleanup();
99251876Speter    ENGINE_cleanup();
100251876Speter    return APR_SUCCESS;
101251876Speter}
102251876Speter
103251876Speterstatic apr_status_t crypto_shutdown_helper(void *data)
104251876Speter{
105251876Speter    return crypto_shutdown();
106251876Speter}
107251876Speter
108251876Speter/**
109251876Speter * Initialise the crypto library and perform one time initialisation.
110251876Speter */
111253734Speterstatic apr_status_t crypto_init(apr_pool_t *pool, const char *params,
112253734Speter        const apu_err_t **result)
113251876Speter{
114251876Speter    CRYPTO_malloc_init();
115251876Speter    ERR_load_crypto_strings();
116251876Speter    /* SSL_load_error_strings(); */
117251876Speter    OpenSSL_add_all_algorithms();
118251876Speter    ENGINE_load_builtin_engines();
119251876Speter    ENGINE_register_all_complete();
120251876Speter
121251876Speter    apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper,
122251876Speter            apr_pool_cleanup_null);
123251876Speter
124251876Speter    return APR_SUCCESS;
125251876Speter}
126251876Speter
127251876Speter/**
128251876Speter * @brief Clean encryption / decryption context.
129251876Speter * @note After cleanup, a context is free to be reused if necessary.
130251876Speter * @param ctx The block context to use.
131251876Speter * @return Returns APR_ENOTIMPL if not supported.
132251876Speter */
133251876Speterstatic apr_status_t crypto_block_cleanup(apr_crypto_block_t *ctx)
134251876Speter{
135251876Speter
136251876Speter    if (ctx->initialised) {
137251876Speter        EVP_CIPHER_CTX_cleanup(&ctx->cipherCtx);
138251876Speter        ctx->initialised = 0;
139251876Speter    }
140251876Speter
141251876Speter    return APR_SUCCESS;
142251876Speter
143251876Speter}
144251876Speter
145251876Speterstatic apr_status_t crypto_block_cleanup_helper(void *data)
146251876Speter{
147251876Speter    apr_crypto_block_t *block = (apr_crypto_block_t *) data;
148251876Speter    return crypto_block_cleanup(block);
149251876Speter}
150251876Speter
151251876Speter/**
152251876Speter * @brief Clean encryption / decryption context.
153251876Speter * @note After cleanup, a context is free to be reused if necessary.
154251876Speter * @param f The context to use.
155251876Speter * @return Returns APR_ENOTIMPL if not supported.
156251876Speter */
157251876Speterstatic apr_status_t crypto_cleanup(apr_crypto_t *f)
158251876Speter{
159251876Speter
160251876Speter    if (f->config->engine) {
161251876Speter        ENGINE_finish(f->config->engine);
162251876Speter        ENGINE_free(f->config->engine);
163251876Speter        f->config->engine = NULL;
164251876Speter    }
165251876Speter    return APR_SUCCESS;
166251876Speter
167251876Speter}
168251876Speter
169251876Speterstatic apr_status_t crypto_cleanup_helper(void *data)
170251876Speter{
171251876Speter    apr_crypto_t *f = (apr_crypto_t *) data;
172251876Speter    return crypto_cleanup(f);
173251876Speter}
174251876Speter
175251876Speter/**
176251876Speter * @brief Create a context for supporting encryption. Keys, certificates,
177251876Speter *        algorithms and other parameters will be set per context. More than
178251876Speter *        one context can be created at one time. A cleanup will be automatically
179251876Speter *        registered with the given pool to guarantee a graceful shutdown.
180251876Speter * @param f - context pointer will be written here
181251876Speter * @param provider - provider to use
182251876Speter * @param params - array of key parameters
183251876Speter * @param pool - process pool
184251876Speter * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
185251876Speter * if the engine cannot be initialised.
186251876Speter */
187251876Speterstatic apr_status_t crypto_make(apr_crypto_t **ff,
188251876Speter        const apr_crypto_driver_t *provider, const char *params,
189251876Speter        apr_pool_t *pool)
190251876Speter{
191251876Speter    apr_crypto_config_t *config = NULL;
192251876Speter    apr_crypto_t *f = apr_pcalloc(pool, sizeof(apr_crypto_t));
193251876Speter
194251876Speter    const char *engine = NULL;
195251876Speter
196251876Speter    struct {
197251876Speter        const char *field;
198251876Speter        const char *value;
199251876Speter        int set;
200251876Speter    } fields[] = {
201251876Speter        { "engine", NULL, 0 },
202251876Speter        { NULL, NULL, 0 }
203251876Speter    };
204251876Speter    const char *ptr;
205251876Speter    size_t klen;
206251876Speter    char **elts = NULL;
207251876Speter    char *elt;
208251876Speter    int i = 0, j;
209251876Speter    apr_status_t status;
210251876Speter
211251876Speter    if (params) {
212251876Speter        if (APR_SUCCESS != (status = apr_tokenize_to_argv(params, &elts, pool))) {
213251876Speter            return status;
214251876Speter        }
215251876Speter        while ((elt = elts[i])) {
216251876Speter            ptr = strchr(elt, '=');
217251876Speter            if (ptr) {
218251876Speter                for (klen = ptr - elt; klen && apr_isspace(elt[klen - 1]); --klen)
219251876Speter                    ;
220251876Speter                ptr++;
221251876Speter            }
222251876Speter            else {
223251876Speter                for (klen = strlen(elt); klen && apr_isspace(elt[klen - 1]); --klen)
224251876Speter                    ;
225251876Speter            }
226251876Speter            elt[klen] = 0;
227251876Speter
228251876Speter            for (j = 0; fields[j].field != NULL; ++j) {
229251876Speter                if (!strcasecmp(fields[j].field, elt)) {
230251876Speter                    fields[j].set = 1;
231251876Speter                    if (ptr) {
232251876Speter                        fields[j].value = ptr;
233251876Speter                    }
234251876Speter                    break;
235251876Speter                }
236251876Speter            }
237251876Speter
238251876Speter            i++;
239251876Speter        }
240251876Speter        engine = fields[0].value;
241251876Speter    }
242251876Speter
243251876Speter    if (!f) {
244251876Speter        return APR_ENOMEM;
245251876Speter    }
246251876Speter    *ff = f;
247251876Speter    f->pool = pool;
248251876Speter    f->provider = provider;
249251876Speter    config = f->config = apr_pcalloc(pool, sizeof(apr_crypto_config_t));
250251876Speter    if (!config) {
251251876Speter        return APR_ENOMEM;
252251876Speter    }
253251876Speter
254251876Speter    f->result = apr_pcalloc(pool, sizeof(apu_err_t));
255251876Speter    if (!f->result) {
256251876Speter        return APR_ENOMEM;
257251876Speter    }
258251876Speter
259251876Speter    f->keys = apr_array_make(pool, 10, sizeof(apr_crypto_key_t));
260251876Speter    if (!f->keys) {
261251876Speter        return APR_ENOMEM;
262251876Speter    }
263251876Speter
264251876Speter    f->types = apr_hash_make(pool);
265251876Speter    if (!f->types) {
266251876Speter        return APR_ENOMEM;
267251876Speter    }
268251876Speter    apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_3des_192));
269251876Speter    apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_aes_128));
270251876Speter    apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_aes_192));
271251876Speter    apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_aes_256));
272251876Speter
273251876Speter    f->modes = apr_hash_make(pool);
274251876Speter    if (!f->modes) {
275251876Speter        return APR_ENOMEM;
276251876Speter    }
277251876Speter    apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(mode_ecb));
278251876Speter    apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(mode_cbc));
279251876Speter
280251876Speter    apr_pool_cleanup_register(pool, f, crypto_cleanup_helper,
281251876Speter            apr_pool_cleanup_null);
282251876Speter
283251876Speter    if (engine) {
284251876Speter        config->engine = ENGINE_by_id(engine);
285251876Speter        if (!config->engine) {
286251876Speter            return APR_ENOENGINE;
287251876Speter        }
288251876Speter        if (!ENGINE_init(config->engine)) {
289251876Speter            ENGINE_free(config->engine);
290251876Speter            config->engine = NULL;
291251876Speter            return APR_EINITENGINE;
292251876Speter        }
293251876Speter    }
294251876Speter
295251876Speter    return APR_SUCCESS;
296251876Speter
297251876Speter}
298251876Speter
299251876Speter/**
300251876Speter * @brief Get a hash table of key types, keyed by the name of the type against
301251876Speter * an integer pointer constant.
302251876Speter *
303251876Speter * @param types - hashtable of key types keyed to constants.
304251876Speter * @param f - encryption context
305251876Speter * @return APR_SUCCESS for success
306251876Speter */
307251876Speterstatic apr_status_t crypto_get_block_key_types(apr_hash_t **types,
308251876Speter        const apr_crypto_t *f)
309251876Speter{
310251876Speter    *types = f->types;
311251876Speter    return APR_SUCCESS;
312251876Speter}
313251876Speter
314251876Speter/**
315251876Speter * @brief Get a hash table of key modes, keyed by the name of the mode against
316251876Speter * an integer pointer constant.
317251876Speter *
318251876Speter * @param modes - hashtable of key modes keyed to constants.
319251876Speter * @param f - encryption context
320251876Speter * @return APR_SUCCESS for success
321251876Speter */
322251876Speterstatic apr_status_t crypto_get_block_key_modes(apr_hash_t **modes,
323251876Speter        const apr_crypto_t *f)
324251876Speter{
325251876Speter    *modes = f->modes;
326251876Speter    return APR_SUCCESS;
327251876Speter}
328251876Speter
329251876Speter/**
330251876Speter * @brief Create a key from the given passphrase. By default, the PBKDF2
331251876Speter *        algorithm is used to generate the key from the passphrase. It is expected
332251876Speter *        that the same pass phrase will generate the same key, regardless of the
333251876Speter *        backend crypto platform used. The key is cleaned up when the context
334251876Speter *        is cleaned, and may be reused with multiple encryption or decryption
335251876Speter *        operations.
336251876Speter * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
337251876Speter *       *key is not NULL, *key must point at a previously created structure.
338251876Speter * @param key The key returned, see note.
339251876Speter * @param ivSize The size of the initialisation vector will be returned, based
340251876Speter *               on whether an IV is relevant for this type of crypto.
341251876Speter * @param pass The passphrase to use.
342251876Speter * @param passLen The passphrase length in bytes
343251876Speter * @param salt The salt to use.
344251876Speter * @param saltLen The salt length in bytes
345251876Speter * @param type 3DES_192, AES_128, AES_192, AES_256.
346251876Speter * @param mode Electronic Code Book / Cipher Block Chaining.
347251876Speter * @param doPad Pad if necessary.
348251876Speter * @param iterations Iteration count
349251876Speter * @param f The context to use.
350251876Speter * @param p The pool to use.
351251876Speter * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
352251876Speter *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
353251876Speter *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
354251876Speter *         not known. APR_EPADDING if padding was requested but is not supported.
355251876Speter *         APR_ENOTIMPL if not implemented.
356251876Speter */
357251876Speterstatic apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
358251876Speter        const char *pass, apr_size_t passLen, const unsigned char * salt,
359251876Speter        apr_size_t saltLen, const apr_crypto_block_key_type_e type,
360251876Speter        const apr_crypto_block_key_mode_e mode, const int doPad,
361251876Speter        const int iterations, const apr_crypto_t *f, apr_pool_t *p)
362251876Speter{
363251876Speter    apr_crypto_key_t *key = *k;
364251876Speter
365251876Speter    if (!key) {
366251876Speter        *k = key = apr_array_push(f->keys);
367251876Speter    }
368251876Speter    if (!key) {
369251876Speter        return APR_ENOMEM;
370251876Speter    }
371251876Speter
372251876Speter    key->f = f;
373251876Speter    key->provider = f->provider;
374251876Speter
375251876Speter    /* determine the cipher to be used */
376251876Speter    switch (type) {
377251876Speter
378251876Speter    case (APR_KEY_3DES_192):
379251876Speter
380251876Speter        /* A 3DES key */
381251876Speter        if (mode == APR_MODE_CBC) {
382251876Speter            key->cipher = EVP_des_ede3_cbc();
383251876Speter        }
384251876Speter        else {
385251876Speter            key->cipher = EVP_des_ede3_ecb();
386251876Speter        }
387251876Speter        break;
388251876Speter
389251876Speter    case (APR_KEY_AES_128):
390251876Speter
391251876Speter        if (mode == APR_MODE_CBC) {
392251876Speter            key->cipher = EVP_aes_128_cbc();
393251876Speter        }
394251876Speter        else {
395251876Speter            key->cipher = EVP_aes_128_ecb();
396251876Speter        }
397251876Speter        break;
398251876Speter
399251876Speter    case (APR_KEY_AES_192):
400251876Speter
401251876Speter        if (mode == APR_MODE_CBC) {
402251876Speter            key->cipher = EVP_aes_192_cbc();
403251876Speter        }
404251876Speter        else {
405251876Speter            key->cipher = EVP_aes_192_ecb();
406251876Speter        }
407251876Speter        break;
408251876Speter
409251876Speter    case (APR_KEY_AES_256):
410251876Speter
411251876Speter        if (mode == APR_MODE_CBC) {
412251876Speter            key->cipher = EVP_aes_256_cbc();
413251876Speter        }
414251876Speter        else {
415251876Speter            key->cipher = EVP_aes_256_ecb();
416251876Speter        }
417251876Speter        break;
418251876Speter
419251876Speter    default:
420251876Speter
421251876Speter        /* unknown key type, give up */
422251876Speter        return APR_EKEYTYPE;
423251876Speter
424251876Speter    }
425251876Speter
426251876Speter    /* find the length of the key we need */
427251876Speter    key->keyLen = EVP_CIPHER_key_length(key->cipher);
428251876Speter
429251876Speter    /* make space for the key */
430251876Speter    key->key = apr_pcalloc(p, key->keyLen);
431251876Speter    if (!key->key) {
432251876Speter        return APR_ENOMEM;
433251876Speter    }
434251876Speter    apr_crypto_clear(p, key->key, key->keyLen);
435251876Speter
436251876Speter    /* generate the key */
437251876Speter    if (PKCS5_PBKDF2_HMAC_SHA1(pass, passLen, (unsigned char *) salt, saltLen,
438251876Speter            iterations, key->keyLen, key->key) == 0) {
439251876Speter        return APR_ENOKEY;
440251876Speter    }
441251876Speter
442251876Speter    key->doPad = doPad;
443251876Speter
444251876Speter    /* note: openssl incorrectly returns non zero IV size values for ECB
445251876Speter     * algorithms, so work around this by ignoring the IV size.
446251876Speter     */
447251876Speter    if (APR_MODE_ECB != mode) {
448251876Speter        key->ivSize = EVP_CIPHER_iv_length(key->cipher);
449251876Speter    }
450251876Speter    if (ivSize) {
451251876Speter        *ivSize = key->ivSize;
452251876Speter    }
453251876Speter
454251876Speter    return APR_SUCCESS;
455251876Speter}
456251876Speter
457251876Speter/**
458251876Speter * @brief Initialise a context for encrypting arbitrary data using the given key.
459251876Speter * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
460251876Speter *       *ctx is not NULL, *ctx must point at a previously created structure.
461251876Speter * @param ctx The block context returned, see note.
462251876Speter * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
463251876Speter *           an IV will be created at random, in space allocated from the pool.
464251876Speter *           If the buffer pointed to is not NULL, the IV in the buffer will be
465251876Speter *           used.
466251876Speter * @param key The key structure.
467251876Speter * @param blockSize The block size of the cipher.
468251876Speter * @param p The pool to use.
469251876Speter * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
470251876Speter *         Returns APR_EINIT if the backend failed to initialise the context. Returns
471251876Speter *         APR_ENOTIMPL if not implemented.
472251876Speter */
473251876Speterstatic apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
474251876Speter        const unsigned char **iv, const apr_crypto_key_t *key,
475251876Speter        apr_size_t *blockSize, apr_pool_t *p)
476251876Speter{
477251876Speter    unsigned char *usedIv;
478251876Speter    apr_crypto_config_t *config = key->f->config;
479251876Speter    apr_crypto_block_t *block = *ctx;
480251876Speter    if (!block) {
481251876Speter        *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
482251876Speter    }
483251876Speter    if (!block) {
484251876Speter        return APR_ENOMEM;
485251876Speter    }
486251876Speter    block->f = key->f;
487251876Speter    block->pool = p;
488251876Speter    block->provider = key->provider;
489251876Speter
490251876Speter    apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
491251876Speter            apr_pool_cleanup_null);
492251876Speter
493251876Speter    /* create a new context for encryption */
494251876Speter    EVP_CIPHER_CTX_init(&block->cipherCtx);
495251876Speter    block->initialised = 1;
496251876Speter
497251876Speter    /* generate an IV, if necessary */
498251876Speter    usedIv = NULL;
499251876Speter    if (key->ivSize) {
500251876Speter        if (iv == NULL) {
501251876Speter            return APR_ENOIV;
502251876Speter        }
503251876Speter        if (*iv == NULL) {
504251876Speter            usedIv = apr_pcalloc(p, key->ivSize);
505251876Speter            if (!usedIv) {
506251876Speter                return APR_ENOMEM;
507251876Speter            }
508251876Speter            apr_crypto_clear(p, usedIv, key->ivSize);
509251876Speter            if (!((RAND_status() == 1)
510251876Speter                    && (RAND_bytes(usedIv, key->ivSize) == 1))) {
511251876Speter                return APR_ENOIV;
512251876Speter            }
513251876Speter            *iv = usedIv;
514251876Speter        }
515251876Speter        else {
516251876Speter            usedIv = (unsigned char *) *iv;
517251876Speter        }
518251876Speter    }
519251876Speter
520251876Speter    /* set up our encryption context */
521251876Speter#if CRYPTO_OPENSSL_CONST_BUFFERS
522251876Speter    if (!EVP_EncryptInit_ex(&block->cipherCtx, key->cipher, config->engine,
523251876Speter            key->key, usedIv)) {
524251876Speter#else
525251876Speter        if (!EVP_EncryptInit_ex(&block->cipherCtx, key->cipher, config->engine, (unsigned char *) key->key, (unsigned char *) usedIv)) {
526251876Speter#endif
527251876Speter        return APR_EINIT;
528251876Speter    }
529251876Speter
530251876Speter    /* Clear up any read padding */
531251876Speter    if (!EVP_CIPHER_CTX_set_padding(&block->cipherCtx, key->doPad)) {
532251876Speter        return APR_EPADDING;
533251876Speter    }
534251876Speter
535251876Speter    if (blockSize) {
536251876Speter        *blockSize = EVP_CIPHER_block_size(key->cipher);
537251876Speter    }
538251876Speter
539251876Speter    return APR_SUCCESS;
540251876Speter
541251876Speter}
542251876Speter
543251876Speter/**
544251876Speter * @brief Encrypt data provided by in, write it to out.
545251876Speter * @note The number of bytes written will be written to outlen. If
546251876Speter *       out is NULL, outlen will contain the maximum size of the
547251876Speter *       buffer needed to hold the data, including any data
548251876Speter *       generated by apr_crypto_block_encrypt_finish below. If *out points
549251876Speter *       to NULL, a buffer sufficiently large will be created from
550251876Speter *       the pool provided. If *out points to a not-NULL value, this
551251876Speter *       value will be used as a buffer instead.
552251876Speter * @param out Address of a buffer to which data will be written,
553251876Speter *        see note.
554251876Speter * @param outlen Length of the output will be written here.
555251876Speter * @param in Address of the buffer to read.
556251876Speter * @param inlen Length of the buffer to read.
557251876Speter * @param ctx The block context to use.
558251876Speter * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
559251876Speter *         not implemented.
560251876Speter */
561251876Speterstatic apr_status_t crypto_block_encrypt(unsigned char **out,
562251876Speter        apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
563251876Speter        apr_crypto_block_t *ctx)
564251876Speter{
565251876Speter    int outl = *outlen;
566251876Speter    unsigned char *buffer;
567251876Speter
568251876Speter    /* are we after the maximum size of the out buffer? */
569251876Speter    if (!out) {
570251876Speter        *outlen = inlen + EVP_MAX_BLOCK_LENGTH;
571251876Speter        return APR_SUCCESS;
572251876Speter    }
573251876Speter
574251876Speter    /* must we allocate the output buffer from a pool? */
575251876Speter    if (!*out) {
576251876Speter        buffer = apr_palloc(ctx->pool, inlen + EVP_MAX_BLOCK_LENGTH);
577251876Speter        if (!buffer) {
578251876Speter            return APR_ENOMEM;
579251876Speter        }
580251876Speter        apr_crypto_clear(ctx->pool, buffer, inlen + EVP_MAX_BLOCK_LENGTH);
581251876Speter        *out = buffer;
582251876Speter    }
583251876Speter
584251876Speter#if CRYPT_OPENSSL_CONST_BUFFERS
585251876Speter    if (!EVP_EncryptUpdate(&ctx->cipherCtx, (*out), &outl, in, inlen)) {
586251876Speter#else
587251876Speter    if (!EVP_EncryptUpdate(&ctx->cipherCtx, (*out), &outl,
588251876Speter            (unsigned char *) in, inlen)) {
589251876Speter#endif
590251876Speter        return APR_ECRYPT;
591251876Speter    }
592251876Speter    *outlen = outl;
593251876Speter
594251876Speter    return APR_SUCCESS;
595251876Speter
596251876Speter}
597251876Speter
598251876Speter/**
599251876Speter * @brief Encrypt final data block, write it to out.
600251876Speter * @note If necessary the final block will be written out after being
601251876Speter *       padded. Typically the final block will be written to the
602251876Speter *       same buffer used by apr_crypto_block_encrypt, offset by the
603251876Speter *       number of bytes returned as actually written by the
604251876Speter *       apr_crypto_block_encrypt() call. After this call, the context
605251876Speter *       is cleaned and can be reused by apr_crypto_block_encrypt_init().
606251876Speter * @param out Address of a buffer to which data will be written. This
607251876Speter *            buffer must already exist, and is usually the same
608251876Speter *            buffer used by apr_evp_crypt(). See note.
609251876Speter * @param outlen Length of the output will be written here.
610251876Speter * @param ctx The block context to use.
611251876Speter * @return APR_ECRYPT if an error occurred.
612251876Speter * @return APR_EPADDING if padding was enabled and the block was incorrectly
613251876Speter *         formatted.
614251876Speter * @return APR_ENOTIMPL if not implemented.
615251876Speter */
616251876Speterstatic apr_status_t crypto_block_encrypt_finish(unsigned char *out,
617251876Speter        apr_size_t *outlen, apr_crypto_block_t *ctx)
618251876Speter{
619251876Speter    int len = *outlen;
620251876Speter
621251876Speter    if (EVP_EncryptFinal_ex(&ctx->cipherCtx, out, &len) == 0) {
622251876Speter        return APR_EPADDING;
623251876Speter    }
624251876Speter    *outlen = len;
625251876Speter
626251876Speter    return APR_SUCCESS;
627251876Speter
628251876Speter}
629251876Speter
630251876Speter/**
631251876Speter * @brief Initialise a context for decrypting arbitrary data using the given key.
632251876Speter * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
633251876Speter *       *ctx is not NULL, *ctx must point at a previously created structure.
634251876Speter * @param ctx The block context returned, see note.
635251876Speter * @param blockSize The block size of the cipher.
636251876Speter * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
637251876Speter *           an IV will be created at random, in space allocated from the pool.
638251876Speter *           If the buffer is not NULL, the IV in the buffer will be used.
639251876Speter * @param key The key structure.
640251876Speter * @param p The pool to use.
641251876Speter * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
642251876Speter *         Returns APR_EINIT if the backend failed to initialise the context. Returns
643251876Speter *         APR_ENOTIMPL if not implemented.
644251876Speter */
645251876Speterstatic apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
646251876Speter        apr_size_t *blockSize, const unsigned char *iv,
647251876Speter        const apr_crypto_key_t *key, apr_pool_t *p)
648251876Speter{
649251876Speter    apr_crypto_config_t *config = key->f->config;
650251876Speter    apr_crypto_block_t *block = *ctx;
651251876Speter    if (!block) {
652251876Speter        *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
653251876Speter    }
654251876Speter    if (!block) {
655251876Speter        return APR_ENOMEM;
656251876Speter    }
657251876Speter    block->f = key->f;
658251876Speter    block->pool = p;
659251876Speter    block->provider = key->provider;
660251876Speter
661251876Speter    apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
662251876Speter            apr_pool_cleanup_null);
663251876Speter
664251876Speter    /* create a new context for encryption */
665251876Speter    EVP_CIPHER_CTX_init(&block->cipherCtx);
666251876Speter    block->initialised = 1;
667251876Speter
668251876Speter    /* generate an IV, if necessary */
669251876Speter    if (key->ivSize) {
670251876Speter        if (iv == NULL) {
671251876Speter            return APR_ENOIV;
672251876Speter        }
673251876Speter    }
674251876Speter
675251876Speter    /* set up our encryption context */
676251876Speter#if CRYPTO_OPENSSL_CONST_BUFFERS
677251876Speter    if (!EVP_DecryptInit_ex(&block->cipherCtx, key->cipher, config->engine,
678251876Speter            key->key, iv)) {
679251876Speter#else
680251876Speter        if (!EVP_DecryptInit_ex(&block->cipherCtx, key->cipher, config->engine, (unsigned char *) key->key, (unsigned char *) iv)) {
681251876Speter#endif
682251876Speter        return APR_EINIT;
683251876Speter    }
684251876Speter
685251876Speter    /* Clear up any read padding */
686251876Speter    if (!EVP_CIPHER_CTX_set_padding(&block->cipherCtx, key->doPad)) {
687251876Speter        return APR_EPADDING;
688251876Speter    }
689251876Speter
690251876Speter    if (blockSize) {
691251876Speter        *blockSize = EVP_CIPHER_block_size(key->cipher);
692251876Speter    }
693251876Speter
694251876Speter    return APR_SUCCESS;
695251876Speter
696251876Speter}
697251876Speter
698251876Speter/**
699251876Speter * @brief Decrypt data provided by in, write it to out.
700251876Speter * @note The number of bytes written will be written to outlen. If
701251876Speter *       out is NULL, outlen will contain the maximum size of the
702251876Speter *       buffer needed to hold the data, including any data
703251876Speter *       generated by apr_crypto_block_decrypt_finish below. If *out points
704251876Speter *       to NULL, a buffer sufficiently large will be created from
705251876Speter *       the pool provided. If *out points to a not-NULL value, this
706251876Speter *       value will be used as a buffer instead.
707251876Speter * @param out Address of a buffer to which data will be written,
708251876Speter *        see note.
709251876Speter * @param outlen Length of the output will be written here.
710251876Speter * @param in Address of the buffer to read.
711251876Speter * @param inlen Length of the buffer to read.
712251876Speter * @param ctx The block context to use.
713251876Speter * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
714251876Speter *         not implemented.
715251876Speter */
716251876Speterstatic apr_status_t crypto_block_decrypt(unsigned char **out,
717251876Speter        apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
718251876Speter        apr_crypto_block_t *ctx)
719251876Speter{
720251876Speter    int outl = *outlen;
721251876Speter    unsigned char *buffer;
722251876Speter
723251876Speter    /* are we after the maximum size of the out buffer? */
724251876Speter    if (!out) {
725251876Speter        *outlen = inlen + EVP_MAX_BLOCK_LENGTH;
726251876Speter        return APR_SUCCESS;
727251876Speter    }
728251876Speter
729251876Speter    /* must we allocate the output buffer from a pool? */
730251876Speter    if (!(*out)) {
731251876Speter        buffer = apr_palloc(ctx->pool, inlen + EVP_MAX_BLOCK_LENGTH);
732251876Speter        if (!buffer) {
733251876Speter            return APR_ENOMEM;
734251876Speter        }
735251876Speter        apr_crypto_clear(ctx->pool, buffer, inlen + EVP_MAX_BLOCK_LENGTH);
736251876Speter        *out = buffer;
737251876Speter    }
738251876Speter
739251876Speter#if CRYPT_OPENSSL_CONST_BUFFERS
740251876Speter    if (!EVP_DecryptUpdate(&ctx->cipherCtx, *out, &outl, in, inlen)) {
741251876Speter#else
742251876Speter    if (!EVP_DecryptUpdate(&ctx->cipherCtx, *out, &outl, (unsigned char *) in,
743251876Speter            inlen)) {
744251876Speter#endif
745251876Speter        return APR_ECRYPT;
746251876Speter    }
747251876Speter    *outlen = outl;
748251876Speter
749251876Speter    return APR_SUCCESS;
750251876Speter
751251876Speter}
752251876Speter
753251876Speter/**
754251876Speter * @brief Decrypt final data block, write it to out.
755251876Speter * @note If necessary the final block will be written out after being
756251876Speter *       padded. Typically the final block will be written to the
757251876Speter *       same buffer used by apr_crypto_block_decrypt, offset by the
758251876Speter *       number of bytes returned as actually written by the
759251876Speter *       apr_crypto_block_decrypt() call. After this call, the context
760251876Speter *       is cleaned and can be reused by apr_crypto_block_decrypt_init().
761251876Speter * @param out Address of a buffer to which data will be written. This
762251876Speter *            buffer must already exist, and is usually the same
763251876Speter *            buffer used by apr_evp_crypt(). See note.
764251876Speter * @param outlen Length of the output will be written here.
765251876Speter * @param ctx The block context to use.
766251876Speter * @return APR_ECRYPT if an error occurred.
767251876Speter * @return APR_EPADDING if padding was enabled and the block was incorrectly
768251876Speter *         formatted.
769251876Speter * @return APR_ENOTIMPL if not implemented.
770251876Speter */
771251876Speterstatic apr_status_t crypto_block_decrypt_finish(unsigned char *out,
772251876Speter        apr_size_t *outlen, apr_crypto_block_t *ctx)
773251876Speter{
774251876Speter
775251876Speter    int len = *outlen;
776251876Speter
777251876Speter    if (EVP_DecryptFinal_ex(&ctx->cipherCtx, out, &len) == 0) {
778251876Speter        return APR_EPADDING;
779251876Speter    }
780251876Speter    *outlen = len;
781251876Speter
782251876Speter    return APR_SUCCESS;
783251876Speter
784251876Speter}
785251876Speter
786251876Speter/**
787251876Speter * OpenSSL module.
788251876Speter */
789251876SpeterAPU_MODULE_DECLARE_DATA const apr_crypto_driver_t apr_crypto_openssl_driver = {
790251876Speter    "openssl", crypto_init, crypto_make, crypto_get_block_key_types,
791251876Speter    crypto_get_block_key_modes, crypto_passphrase,
792251876Speter    crypto_block_encrypt_init, crypto_block_encrypt,
793251876Speter    crypto_block_encrypt_finish, crypto_block_decrypt_init,
794251876Speter    crypto_block_decrypt, crypto_block_decrypt_finish,
795251876Speter    crypto_block_cleanup, crypto_cleanup, crypto_shutdown, crypto_error
796251876Speter};
797251876Speter
798251876Speter#endif
799