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